home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-11 | 220.3 KB | 4,589 lines |
- ░░░░░░▄ ░░░▄ ░░▄ ░░░░░░▄ ░░▄ ░░▄ ░░░░▄ ░░░░░░▄
- ░░█▀░░█ ░░░░▄░░█ ░░█▀▀ ░░█ ░░█ ░░█▀▀▀ ░░█▀░░█
- ░░░░░░█ ░░█░░░░█ ░░█ ░░░░░░▄ ░░█ ░░█ ░░█░░░▄ ░░░░░░█
- ░░█▀░░█ ░░█ ░░░█ ░░█ ▀▀▀▀▀▀ ░█ ░█▀ ░░█ ░░█ ░░█▀░░█
- ░░█ ░░█ ░░█ ░░█ ░░░░░░▄ ░░█▀ ░░░░█▀ ░░█ ░░█
- ▀▀ ▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
-
-
- ░░░░░▄ ░░░░░░▄ ░░░░▄
- ░░█▀░░▄ ░░█▀░░█ ░░█▀░░▄
- ░░█ ░░█ ░░█ ░░█ ░░█ ▀▀
- ░░█ ░░█ ░░█ ░░█ ░░█ ░░▄
- ░░▄ ░░░░░█▀ ░░░░░░█ ░░░░█▀
- ▀▀ ▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀▀▀
-
- (English documentation)
-
- ┌─────────────────────────────────────────────┐
- │ AniVGA │
- │ a sprite-unit for TurboPascal ≥V6.0 │
- │ by Kai Rohrbacher │
- │ Version 1.2 │
- └─────────────────────────────────────────────┘
-
-
- Purpose : Animation of sprites on a VGA's 320x200x256 mode and
- TurboPascal ≥V6.0
- Author : Kai Rohrbacher
- Germany
- Internet: S_ROHRBACHER@IRAVCL.IRA.UKA.DE
- Bitnet : UKB8@DKAUNI2.BITNET
- FIDO : 2:241/7451.7 (aka Kai.Rohrbacher@logo.ka.sub.org)
- (note: due to the German putsch in FIDO, you
- won't reach me at 2:241/7451 if writing from
- outside Germany!)
- Language: TurboPascal V6.0
- Date : June 1993
-
- ---------------------------------------------------------------------
- Always remember: "I know my English spelling is bad, but if I used my
- own language you probably couldn't read it at all."
- -- Nico de Vries
- ---------------------------------------------------------------------
-
- 0. Table of contents
- ────────────────────
-
- 1. Prélude: Legal Notices
- 2. What is AniVGA? How to install?
- 3. Features and Restrictions of AniVGA
- 4. "HELLO WORLD" - A First Example
- 5. How AniVGA works
- 6. Tips, tricks and techniques
- 7. Credits
- 8. AniVGA Reference Manual
-
-
- 1. Prélude: Legal Notices
- ─────────────────────────
-
- Okay, the boring stuff first...
-
- The author hereby disclaims all warranties relating to this software,
- whether expressed or implied, including without limitation any implied
- warranties of merchantability or fitness for a particular purpose.
- I will not be liable for any special, incidental, consequential, indirect
- or similar damages due to loss of data/damage to hardware or any other
- reason, even if I have been advised of the possibility of such damages.
-
- This programming toolkit is released as "freeware" by the author.
- It is however copyrighted and all rights and ownership are kept with the
- author. You may use it, copy it and give it to everybody as long as no
- modifications are made -- but don't try to sell it (or part of it)!
- You may freely copy and give away this program package as long as you...
- a) don't make any changes to the code -and-
- b) don't omit any files from the archive
-
- All programs you realize with this software package may be distributed/sold
- freely - the only thing I ask you for is to mention the use of this toolkit
- in your program and to send me a copy of your program, although a small
- donation would be *much* appreciated, for the reasons told in the file
- README.2ND (which I hope, you have read thoroughly!).
-
-
- 2. What is AniVGA? How to install?
- ──────────────────────────────────
-
- AniVGA is a powerful toolkit for the animation of sprites on any IBM (or com-
- patible) with a VGA card installed.
- It consists of one (big) unit compilable with TurboPascal ≥V6.0 and some
- utilities to simplify its use:
-
- README.1ST - as it tells you: a text file you should read first
- README.2ND - yes, *exactly* what you are thinking right now...
- ANIVGA.DOC - the manual, you are reading it!
- ANIVGA.TUT - a short tutorial
- ANIVGA.PAS - the source code of the animation unit
- ANIVGA.ENG - as above, but with English comments (automatically
- translated, so don't expect perfect English...)
-
- FAQ.TXT - some frequently asked questions
- CHANGES.TXT - what has changed to the previous version of AniVGA
- WHATSNEW.* - a small demo, showing some changes
-
- COMPRESS.PAS - code of a small compression unit used
- DATEIEN.PAS - code of a unit for file selection menus & screen handling
- EINGABEN.PAS - code of a unit to handle keyboard inputs
-
- BFFFFFFF.PAS - the source code of a (de-)compression program you can use on
- AniVGA's data files
- DUMP_SPR.PAS - the source of a "sprite dumper" which disassembles a (binary)
- sprite file into a (recompilable) ASCII-text
- GRAB.EXE - a TSR-program to grab sprites from other graphics (req. mouse)
- MAKES.PAS - a spritemaker program (requires a mouse and a Super-VGA-card!)
- SHOWPIC.PAS - the source code of a *very* small program to display a *.PIC
- file on the screen
- UNLIB.PAS - the source code of a utility to break apart a library of
- sprites back into its individual sprite files
-
- UNCHAIN.EXE - a nice utility to avoid screen garbage when using TP's
- debugger in 320x200x256x4 graphics mode
- EXAMPL*.PAS - a few _simple_ demo programs
-
- \GRAPHICS\ *.COD, *.LIB, *.PAL, *.PIC
- - some sprites, sprite-libraries, color palettes and pictures,
- used by the demo programs
- \FONT\ *.FNT - the fonts usable by AniVGA
- \JUMPNRUN\*.* - a small (~12K) game done with AniVGA
-
- SVGA256.BGI - a BGI driver, only used for MAKES.EXE
- *.* - documentation, sources, ...
-
-
- Installing AniVGA can be as simple as that (assuming "C:\ANIVGA12\ is the
- directory you want to install the programs):
- - Type "PKUNZIP -d ANIVGA12.ZIP C:\ANIVGA12\" (note the "-d" option to make
- the program expand the subdirectories, too!)
- - Make sure that TPC.EXE is on your path, change into the above directory and
- run MAKE.BAT (which will compile the units & example programs)
- - That's all!
-
- tpc compress
- tpc dateien
- tpc eingaben
- tpc anivga
- tpc bfffffff
- tpc unlib
- tpc dump_spr
- tpc makes
- tpc showpic
- for %%f in (examp*.pas) do tpc %%f
-
- However, if you are a purist in nature :-) then alternatively...
- a) copy COMPRESS.PAS, DATEIEN.PAS, EINGABEN.PAS and ANIVGA.PAS to the
- directory where you keep your TPU's and compile them (in the above order)
- b) copy the examples EXAMPLE?.PAS and all their data files *.COD, *.LIB,
- *.PAL, *.FNT to whereever you keep your PAS-files, or even better: into a
- new subdirectory; do so with the other *.PAS files of the utility programs
- (BFFFFFFF.PAS, UNLIB.PAS, DUMP_SPR.PAS, MAKES.PAS AND SHOWPIC.PAS), too
- c) compile all those *.PAS files; copy the resulting EXEs (and GRAB.EXE) to a
- directory where your PATH-environment variable points to
- d) copy the SVGA256.BGI to whereever you moved MAKES.EXE in step c)
- e) copy the remaining files into a new directory (or the one of step b) )
-
- Note that these are just guidelines, you are free to come up with your own
- ideas where to place the files, as long as the usual TP restrictions are met:
- TP must find its TPUs, and EXEs must find their data files.
- Don't worry, TP is clever enough to tell you if it can't find something and
- what it was looking for.
-
-
- 3. Features and Restrictions of AniVGA
- ──────────────────────────────────────
-
- Some of AniVGA's features are:
-
- - flickerfree animation by a "page-flipping" algorithm and using the
- display enable signal
- - sprite movement in any increments you want
- - arbitrary background image for the animation
- - windowed animations
- - full use of the VGA's 256-color mode
- - several sprite display methods available:
- - sprites can be written normally (covering underlying figures)
- - sprites can be declared to be transparent with regard to the background
- or other sprites pixel by pixel
- - sprites can change their color depending on the underlying background
- image (-> shadow function)
- - display methods can be different for each sprite
- - pixel precise hit-detection routine built in
- - correct clipping of sprites at the screen boundaries
- - up to 32767 different sprites
- - up to 500 sprites may be simultaneously active
- - maximal size of each sprite = 64k
- - maximal size of all loaded sprites only restricted by available memory
- - works with virtual coordinates in the range -16000..+16000
- - thus simple creation of horizontal/vertical "scrolling" games
- - scrolling background image, too
- - several supporting routines to: drawing lines (with built in clipping-
- algorithm), points and graphic-text (incl. clipping), automatic heap
- management for loading of sprites, sprite libraries, background images,
- processor-speed adjustment, palette handling,...
-
- What AniVGA does _not_ support:
- - XMS memory (to slow)
- - resolutions other than 320x200x256 (compatibility question)
-
-
- 4. "HELLO WORLD" - A First Example
- ──────────────────────────────────
-
- AniVGA uses a non-standard 320x200x256 graphic mode, different from the BIOS-
- mode $13, but there should be no problems with all truly compatible VGA cards.
- To see if AniVGA is compatible with your system and to get a first impression
- of its ease of use, compile the following _simple_ program (you can find it on
- disk as file "EXAMPLE1.PAS"):
-
- Notes:
- - Remember to copy and compile AniVGA.PAS in your TurboPascal-Unit-directory
- first!
- - If you want to single-step through the program using TP's built-in debugger,
- then start TP by typing "UNCHAIN TURBO.EXE" (make sure UNCHAIN.EXE is in
- the same directory as TURBO.EXE or somewhere where it will be found by Dos).
- (If you still get screen garbage, then you forgot to enable one or both of
- the options "Graphics screen save" and/or "EGA/VGA palette save" in menu
- Options -> Environment -> Startup)
-
- PROGRAM Example1;
- USES AniVGA,CRT;
- CONST LoadNumber=42; {why not 42? - A hello to all Douglas Adam fans!}
- SpriteName='FLOWER.COD'; {Path and name of the sprite to load}
- Sprite1=0;
- Sprite2=5;
- ch:CHAR=#0; {sets ch to that value everytime the program starts}
- VAR collide:BOOLEAN;
-
- BEGIN
- IF loadSprite(SpriteName,LoadNumber)=0
- THEN BEGIN
- CloseRoutines;
- WRITELN('Error: '+GetErrorMessage); halt(1)
- END;
-
- InitGraph;
-
- Color:=66;
- BackgroundLine(0,0,XMAX,0); BackgroundLine(XMAX,0,XMAX,YMAX);
- BackgroundLine(XMAX,YMAX,0,YMAX); BackgroundLine(0,YMAX,0,0);
- BackgroundOutTextXY(100,70,'Hello world!');
-
- SpriteN[Sprite1]:=LoadNumber;
- SpriteX[Sprite1]:=0; SpriteY[Sprite1]:=0;
-
- SpriteN[Sprite2]:=LoadNumber;
- SpriteX[Sprite2]:=XMAX SHR 1; SpriteY[Sprite2]:=YMAX SHR 1;
-
- Animate;
- REPEAT
- collide:=Hitdetect(Sprite1,Sprite2);
- if collide THEN BEGIN Sound(1000); Delay(5); NoSound END;
- if KeyPressed
- THEN BEGIN
- WHILE KeyPressed do ch:=UpCase(ReadKey);
- CASE ch OF
- 'I':DEC(SpriteY[0]);
- 'J':DEC(SpriteX[0]);
- 'K':INC(SpriteX[0]);
- 'M':INC(SpriteY[0]);
- 'E':dec(StartVirtualY,10); {change position of whole scene with}
- 'S':dec(StartVirtualX,10); {E,S,D,X}
- 'D':inc(StartVirtualX,10);
- 'X':inc(StartVirtualY,10);
- END;
- IF POS(ch,'IJKMESDX')>0 THEN Animate;
- END;
-
- UNTIL (ch='Q') OR (ch=#27);
-
- CloseRoutines;
- END.
-
- (Don't worry if you do not understand the whole program at once - it should
- only give you a first impression of AniVGA's capabilities)
- If you run this program (make sure that the sprite file FLOWER.COD can be
- found by the program!) you should see a graphic consisting of two flowers, a
- rectangle showing the screen boundaries and the words "Hello world" near the
- middle of the screen.
- You can move the top left flower by using the keys "I","J","K","M".
- If you hit the other flower with the first one, the program will beep.
- Try out what happens if you move across the two words in the middle:
- obviously, the two leafs of the sprite behave somehow different: the black
- parts of left leaf are "transparent" in that the writing shines through it,
- while the black parts of the right leaf are "covering black".
- But the writing (which is written in the background image) won't be destroyed.
- As soon as you leave them, the words will be alright again.
- Move the sprite to the very left screen boundary - and move it even more to
- the left: you'll get the impression that it moves off the screen until it is
- totally offscreen.
- Hmmmm - how do we get it back? Sure, "K" will do, but press "S" instead: this
- will "pan" the whole screen 10 pixels to the left (think of that as if you
- could control an imaginary camera to slide to the left), "X" pans into the
- other direction (note the restriction of the program to non-scrolling back-
- ground at this point: the big rectangle and the words "Hello world" won't
- move because they are part of the so-called "static" background image).
- ("E" and "X" will behave similarily, but for the y-direction.)
- Now -using the "I","J","K" and "M" keys- bring back your sprite to the 2nd one
- and let them collide. Press "A" a few times to scroll them both offscreen.
- As you'll notice, the program will not stop beeping: it indicates that the two
- sprites collide, even if they are not visible to you!
- Okay, that should be enough for a first impression, so hit "Q" (or ESC) to
- quit the program, if you've finished wondering... :-)
-
- There are a few more EXAMPLE programs included. They share a common thing:
- they are as small and simple as possible, because they serve only one purpose,
- namely to provide you with some basic techniques!
-
- Run EXAMPLE2.PAS for a demonstration of "scrolling" background; the program is
- much the same as EXAMPLE1, but uses four different "tiles" to build the back-
- ground image. As before, you can use "I,J,K,M" to move your sprite along, but
- this time, you may scroll the whole scene (incl. the background!) with the
- "E,S,D,X" keys, too ("Q" quits, as before).
-
- EXAMPLE3.PAS shows (an extremely) simple use of the "Display_SHADOW" mode to
- display a graphical object and demonstrates the difference to mode
- "Display_SHADOWEXACT": first, a sprite is used for its own shadow zone, simply
- by redrawing it with a little horizontal and vertical offset, using mode
- "Display_SHADOW".
- Although this is a nice trick with many sprites (you don't have to design
- extra shadow sprites this way), it doesn't always work: note that there is one
- area in the flower which differs from what we would expect as shadow: this is
- because AniVGA assumes that everything between the left- and rightmost point
- of a sprite belongs to the sprite's interior and will be drawn accordingly.
- To circumvent this, one would have to draw one (or even several) especially
- designed "shadow zone" sprites for the flower, or use Display_SHADOWEXACT
- instead: just press the space bar to toggle to that mode.
- Pressing "P" draws 1000 randomly distributed points so you can better see the
- shadowing effect for single points.
- Finally, "C" copies part of the screen into memory (with GetImage() ) and
- pastes it somewhere else (with PutImage() ) while clipping off at the screen
- boundaries and is merely there to give a short demonstration of how to use
- these routines.
-
- EXAMPLE4.PAS is an example how to use "sprite cycles": there are six images in
- the sprite (library) file HANTEL.LIB which become "glued" together to form one
- sprite cycle.
- App. one hundred copies of this sprite are then animated on the screen with
- maximum animation speed and again, you can scroll the whole screen area with
- the keys "E","S","D","X". When you do, you will note that as more and more of
- the sprites gets scrolled offscreen, the remaining sprites will rotate faster.
- Pressing the space bar will toggle between fastest animation (no time limit)
- and an animation rate of 200ms per frame.
- You can play around with this value to find out an "optimal" time for your PC
- and this program:
-
- very small: program will show the same symptoms as mentioned above (being
- faster for every sprite offscreen)
- .
- .
- .
- very big : program will slow down even when all sprites are onscreen
-
- Somewhere between lies a value where the animation doesn't get slowed down
- when all sprites are onscreen (=max. work for AniVGA), but stays at the same
- speed for all other cases (=less work for AniVGA).
-
- EXAMPLE5.PAS and EXAMPLE6.PAS are two programs to demonstrate how you can
- build a background image by using tiles: a 2x2 (8x4 respectively) COD-file
- will be loaded and pasted repetively into the virtual screen.
- EXAMPLE6.PAS also shows how you may tie sprites and text output to an absolute
- screen position in scrolling background modes! Besides that, it demonstrates
- usage of a loadable (and multi colored) font.
-
- EXAMPLE7.PAS shows you the same old demo image of the former examples, but
- this time using another palette, loaded from disk.
-
- EXAMPLE8.PAS shows you all opening sequences available by the routine
- "FadeIn()". Press a key A..Z (without Q) to view a method, ESC will quit.
-
- EXAMPLE9.PAS is a simple example to demonstrate how to use an animation
- window by using "SetAnimateWindow()". (Don't forget to look into WHATSNEW.PAS
- for a bigger example).
-
-
- 5. How AniVGA works
- ───────────────────
-
- (It would be _impossible_ trying to cope every detail of AniVGA, but I'm sure
- you will get the basic ideas of AniVGA very soon.)
-
- As already mentioned, the program uses a "tweaked" VGA-graphic mode: the VGA
- is programmed in a way to give 4 graphic pages at a resolution of 320x200
- pixels in 256 colors numbered 0..3.
- Page 0 and 1 are used for the display, page 2 holds the "normal" background
- image and page 3 can contain so-called "tiles" which can be used to build a
- huge background image in "scrolling" background mode.
- (Note for V1.2: the background page has been moved to EMS memory, but this
- doesn't has to bother you)
- The basic idea of the "page flipping" scheme used is that: do everything
- -erasing the old graphic page, draw sprites/lines/pixels/text- on a graphic
- page invisible to the user while showing him a completed page on the screen.
- Then, if finished, "flip" the page, thus making the new, completed page
- visible and the old page to the invisible one. Now start creating the next
- image on this new invisible page - and so on.
- "Erasing" the old image means: overdraw it completely with the background
- image stored in page 2 (or 3), so one could write in pseudo code:
-
- ...
- REPEAT
- show page 0 to user;
- fill (invisible) page 1 with contents of page 2;
- draw new sprites and all other stuff on page 1;
- show page 1 to user;
- fill (invisible) page 0 with contents of page 2;
- draw new sprites and all other stuff on page 0;
- UNTIL DOOMSDAY
- ...
-
- You as the programmer doesn't have to think much about this mechanism, the
- routines keep track of the page flipping automatically: the global variable
- "PAGE" always holds the number of the page which is *invisible* (and thus:
- the page to be drawn upon). Therefore, we say that PAGE holds the "actual
- page" number and 1-PAGE is the page *visible* to the user.
- Most of the procedures and functions of the animation package adjust them-
- selves to the appropriate page; there are only a few situations where you
- have to be aware of this mechanism, mostly when drawing pixels or to create
- special effects.
-
- The whole package is "table driven". That means, the interface to the user
- consists of some tables in which you specify your sprites to be drawn:
- You store into this tables which sprites to draw ("SpriteN[]") and their
- coordinates (in "SpriteX[]" and "SpriteY[]").
- After this, a call of the main routine "Animate()" gives back control to the
- animation routines, which update the graphic screen accordingly:
-
- ...
- REPEAT
- update SpriteN[]-table:
- deactivate sprite i by storing a "0" into SpriteN[i] or
- activate a sprite k by storing k in an unused SpriteN[]-entry or
- let all the other SpriteN[]-entries as they were last cycle
- FOR ALL SpriteN[i]<>0 DO
- IF SpriteN[i] should change its coordinates
- THEN update (SpriteX[i],SpriteY[i]) accordingly
- call Animate() to draw image and display it
- UNTIL you-become-really-bored
- ...
-
- Please note that there are two kinds of "sprite numbers" which should not be
- mixed up: one is a spriteLOAD number and represents a handle to the (physical)
- sprite data, while the other (normally termed "sprite number") is a logical
- number to address this sprite data.
- In the pseudo code given above, "k" is the spriteLOAD number (it is a number
- given at load time) and the index "i" in SpriteN[i] is the sprite number.
- Note that "k" is a unique value: you can think of it as a NAME of the sprite
- data loaded (e.g. you could name the FLOWER.COD data as "123" when loading
- it: there can't be another sprite with the same LOAD-number). On the other
- hand, there could be a hundred flowers on the screen: just choose hundred
- different sprite-table entries (=sprite numbers), e.g. SpriteN[100]..
- SpriteN[199] and store "123" in each of them!
- Whenever you are unsure if you (or I) are speaking of a "sprite number" or a
- "spriteLOAD number", remember that:
-
- ■ A sprite number can hold values in the range 0..NMAX and is an index of
- the tables SpriteX[], SpriteY[] and SpriteN[].
- ■ A spriteLOAD number can hold values between 0..LoadMax and is assigned
- as a "name" to the sprites' physical loaded data; a "0" as load number is
- reserved for "inactivate sprite" (in other words, it is the *content* of
- an entry in SpriteN[])
-
- Example: SpriteN[42]:=0
- │ └ spriteLOAD number
- └ sprite number
-
- The world AniVGA knows is 32000 pixels wide and high, numbered -16000..+16000
- on each axis. Because your graphic screen consists of only 320 by 200 points,
- (ranging from 0..XMAX and 0..YMAX in the x- and y-axis, respectively; (0,0)
- is the upper left corner, (XMAX,YMAX) the lower right one) you can only see
- a small part of this coordinate space, but AniVGA does not distinguish between
- the visible and invisible parts of its world. If, for example, two sprites
- collide, the routine "HitDetect()" will find out, even if this collision
- occurs offscreen.
- Thus you can think of your graphic display being a "camera" to the graphic
- space: your actions can take place everythere in this virtual world, but you
- see only the part displayed by your camera; if you wish to see another part
- of it, you have to move this imaginary camera to that place.
- In AniVGA, you can do this by changing the values "StartVirtualX" and
- "StartVirtualY" which hold the upper left corner of the visual window. As an
- example, let (StartVirtualX,StartVirtualY) be (1000,500): then on your screen
- you will see the part of the world which ranges from coordinates (1000..1319)
- and (500..699) in X- and Y-directions, respectively:
-
- (-16000,-16000)
- - - - - - - - - - - - - - - - - - - - - - - - -
- | | -AniVGA's coordinate space,
- █─────────────────┐-Your terminal 32000x32000 pixels in size
- | │(0,0). │ screen, 320x200 |
- │ . │ pixels in size
- | │ .(319,199)│ |
- └─────────────────┘
- | |
-
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
- (16000,16000)
-
- █ = (StartVirtualX,StartVirtualY)
-
-
- 6. Tips, tricks and techniques
- ──────────────────────────────
-
- There would be a lot of things to say and most of them will be mentioned in
- the following "Reference Manual". Nevertheless, it seems reasonable to repeat
- them in a more concentrated form here, although this happens to make this
- chapter a real topsyturvydom...
-
- a) The ERROR-concept: if an error occurs in one of AniVGA's routines, the
- global variable ERROR will be set accordingly. This gives you the freedom
- either to check this variable each time you called a routine - or ignore
- it for improved speed.
- As a rule of thumb, you should always check this variable while your pro-
- gram is still in the testing phase - and "comment out" these sections when
- you are through with debugging. (Conditional defines are great for that!)
-
- Note that there are some routines that do not set ERROR at all (like
- Screen, GetPixel, PageGetPixel, PagePutPixel), either because in some
- special cases, "nice" tricks can be played with "faulty" parameters or
- because of severe speed improvements! For example, if you are going to
- read a 5000 pixel area from the screen with PageGetPixel(), it would be
- crazy to check 5000 times whether the "page" given to read from is valid
- or not.
-
- Errors which occur by (de)compressing compressed data are "mapped" into
- normal errors of AniVGA, most often "Err_FileIO". AniVGA automatically
- takes care to reset CompressError (the error variable of the compression
- unit) to prevent wrong error messages.
-
- b) Pixel-drawing routines: basically spoken, there are three sorts of graphic
- data objects in AniVGA: sprites, pixels and background images.
- Because of AniVGA's working scheme, all routines handling pixels
- (PutPixel, PagePutPixel, Line, PutImage,...) must be used in a special
- form:
- - If you use them to "draw" into the background page, this can only be
- done when using background mode STATIC (because in mode SCROLLING, the
- background is stored in a compressed "tiling" format one can't access
- directly).
- - Drawing into the background page in mode STATIC is fine (that's the main
- advantage of this mode compared with mode SCROLLING), and the best time
- to do it is _before_ calling Animate(), because changes to the
- background image will then be visible with the call to this routine.
- - Drawing "on the monitor screen" will be visible exactly for one
- animation cycle, that is: until the next call to Animate(). For this
- reason, you must do this changes _after_ calling Animate() and at the
- _visible_ page 1-PAGE (not the _actual_ page PAGE itself).
-
- It is not that difficult as it may sound at first glance; for example:
- ...
- REPEAT
- read_user_inputs; compute_necessary_actions;
- do_all_changes_to_the_background_image;
- do_all_changes_to_the_sprites;
- Animate();
- do_all_changes_to_the_visible_screen;{e.g.:Line(0,0,XMAX,YMAX,1-PAGE)}
- UNTIL user_wants_to_end_application
- ...
-
- This way, after having called Animate(), the changes to the background
- (and your sprites) will be visible (because Animate() has generated an
- appropriate picture) and your changes to this image with the pixel-
- drawing routines will be visible "at once".
- That image will then stay visible until the next call to Animate().
- (Simply spoken, you let Animate() generate and display a picture and then
- do some changes to the picture while it is diplayed)
- - Because of unavoidable memory restrictions, AniVGA can't store pixels
- drawn offscreen: if AniVGA sees that points/lines lie outside the visible
- screen, it just does nothing at all; in other words, you can't draw a
- line outside the screen and "scroll it in" five minutes later! (You would
- have to define the line as a sprite instead, because sprites are the only
- objects stored independently).
-
- c) Coordinates: Throughout all routines, AniVGA works with _virtual_
- coordinates (that is values in the range xε[-16000..+16000],
- yε[-16000..+16000]), but sometimes you will have to address _absolute_
- coordinates (in the range xε[0..XMAX], yε[0..YMAX]), so you have to
- transform virtual coordinates into absolute coordinates (or vice versa),
- which is _very_ easy:
-
- virtual coordinates -> absolute coordinates:
- Xabsolute := Xvirtual - StartVirtualX
- Yabsolute := Yvirtual - StartVirtualY
-
- absolute coordinates -> virtual coordinates:
- Xvirtual := Xabsolute + StartVirtualX
- Yvirtual := Yabsolute + StartVirtualY
-
- d) Background / valid pages: Many routines expect a graphic page number as
- parameter. As mentioned under b), BACKGNDPAGE is valid only when you use
- background mode STATIC. Nevertheless, you could draw to this page even
- when you are using background mode SCROLLING without getting an error
- "Err_InvalidPageNumber" (although you are _strongly_ discouraged to do
- so)!
- That's because you can play some tricks on AniVGA this way, provided that
- you do know _exactly_ what you (and AniVGA) are doing, but this "feature"
- will probably be cut off in future versions of this program.
- (Note that this doesn't mean that you can't switch between STATIC and
- SCROLLING backgrounds during runtime! - It only says that you can't use
- the two background pages _in parallel_ (=at the same time)!)
-
- e) Display objects at the same abolute screen position:
- Let us assume you want to display a score at the upper right corner of the
- screen; that's not hard when using STATIC background: just define your
- score as a sprite and choose an appropriate coordinate pair.
- In SCROLLING mode, your score would scroll away, too, so you must tie it
- to absolute screen coordinates, as said in c), but there is a simple rule
- which can be derived from the equation
-
- absolute_coordinate := virtual_coordinate - StartVirtual_value
-
- To ensure that the absolute (=screen) coordinate stays the same, you have
- to balance out changes done to the StartVirtual-variables like this: when-
- ever you increase/decrease StartVirtualX|Y by some amount delta, increase/
- decrease your score-coordinates by the same amount delta!
- (This results in: new_coord := virtual_coord±delta - (StartVirtual±delta)
- = virtual_coord - StartVirtual = old_coord as wanted)
-
- f) Displaying scores: another way to display a score without defining it as a
- sprite would be to simply draw it to the screen with the pixeldrawing rou-
- tines or OutTextXY():
- ■ draw it to the visible page (1-PAGE) each time after having called
- ANIMATE()
- ■ draw it to the background page BACKGNDPAGE
- The last method is applicable only in background mode STATIC and you have
- to restore the background image in the used area manually, but has the
- advantage that you must redraw your score only when it really changed
- (instead of every animation cycle as with the first method). One way to
- accomplish that would be to use the GetImage() and PutImage() routines:
- ...
- build background image;
- use GetImage() to get a copy of the background area which will be
- overdrawn by the score;
- ...
- main_loop:
- IF new score has to be displayed
- THEN BEGIN
- use PutImage() to restore old background area underneath the
- score
- use OutTextXY() to write new score into the background image
- END
- ...
- ___
-
- Another method to accomplish drawing a score (or something similiar)
- is this: use SetAnimateWindow() to restrict animations to a window smaller
- than your physical terminal size of 320x200 points and draw your score to
- the outer, non-animation area:
- ...
- SetAnimateWindow()
- IF new score has to be displayed
- THEN BEGIN
- UpdateOuterArea:=2 {tell AniVGA to update outer area}
- DoNewScore:=2 {remember this for yourself!}
- END
- ...
- Animate;
- IF DoNewScore<>0
- THEN BEGIN
- draw new score to actual page
- DEC(DoNewScore)
- END
- ...
-
- (Only for the interested reader:
- UpdateOuterArea is a predefined variable in AniVGA, DoNewScore is a
- variable you'll have to define yourself: it's necessary as you normally
- will write your (outer area) graphics to *both* display pages 0 and 1
- and this has to be interleaved properly with AniVGA's actions to wipe
- of the old outer area contents)
-
- g) Speed: It is hard to predict the speed of animations, because that is
- merely determined by the speed of your VGA card, not your computer's CPU
- clock rate! E.g., a program runs faster on my old AT (8MHz) than on a fast
- (25 MHz) 80386 machine - only because of a better VGA card installed in
- the AT!
- Stated otherwise, if you use a computer with "enough" CPU-power, you won't
- have to think much about "should I use STATIC background instead of SCROL-
- LING for improved speed?", because it won't matter much anyway!
- The break even point, where the VGA-card's bottle neck becomes the
- limiting factor depends largely on your application (and your VGA-card, of
- course), but as a rule of thumb, clock speeds faster than 12MHz won't
- improve your program speeds *linearly* any further:
-
- animation ^ ______
- speed │ ___----
- │ /
- │ /
- │/
- ┼─────┬───────────> clock rate
- break-
- even point
-
- Note that your programs will still profit from faster CPU's, but that is
- due to faster computation of all routines not limited by accessing the
- video RAM; even on the fastest clones, the IBM-bus-clock-rate is not
- faster than 10MHz -- and this limits accessing the VGA card: sad, but
- true...
-
- h) DMA access: Quite a long time, I tried to speed up animation rates by
- using the DMA-chip in parallel to the CPU: while the CPU is running your
- program, the DMA should move around memory.
- Unfortunately, I had to find out that most computers don't like DMA
- memory-to-memory transfers at all and those who do don't work when
- addresses used reference the video RAM area. One of you (TNX Mike!) meant
- that's due to the fact that most VGA cards do not decode the necessary
- DMA signals.
- [comment: @!%*!@$ ]
-
- i) Speedup things: Naturally, STATIC background is faster than SCROLLING
- backgrounds, but you can speed up SCROLLING backgrounds, too: make sure
- that StartVirtualX always is a multiple of 4 (that is, StartVirtualX
- MOD 4 = 0), because then, AniVGA can (and will) use the VGA's write
- mode 1 which is a lot faster than normal write mode 0.
- Another idea is to shrink NMAX: if you don't need more than 100 sprites
- (say), then change that constant and recompile AniVGA!
-
- Of course, using SetAnimateWindow() to shrink the animation window
- is another possibility to speed up things.
-
- j) GRAB: If GRAB won't pop up, then save the picture to disk (it's wise to
- do that anyway), run a graphic viewer to merely display the picture and
- capture then.
-
- k) Screen garbage when using the debugger: AniVGA uses a graphics mode unknown
- to TP. Therefore, single stepping or tracing will result in screen garbage.
- To avoid this, just prefix calling TURBO.EXE by UNCHAIN. For example, if
- you normally would type "TURBO.EXE myprog.pas" to start TP's IDE, then now
- type in "UNCHAIN TURBO.EXE myprog.pas". Happy debugging!
-
-
- 7. Credits
- ──────────
-
- Honour to whom honour is due! I would like to thank some people on this way:
-
- - Jordan Hargrave & John Bridges for the SVGA256.BGI driver (out of the
- SuperVGA-driver package SVGABG40.ZIP) used in the sprite maker
- - Colin Buckley for his neat UNCHAIN.EXE utility
- - Ken Pottebaum for his TSR-unit TSRUNIT.ZIP, providing the routines necessary
- to write the Grabsprite-Utility
- - Esra Korte & Robin Leeuwerke for their GAME.PAS demo
- - Joy Mukherjee for supplying the fonts of this package
- - Bernd Klawonn (?) for his principle of using table-driven graphics in the
- first graphics toolkit I ever saw - long, long ago in the "good'ol-AppleII-
- days" (~1985)
- - everybody else I possibly forgot
-
-
- 8. AniVGA Reference Manual
- ──────────────────────────
-
- This reference manual lists all routines, variables, constants and a lot of
- informational stuff concerning AniVGA in alphabetic order.
- Don't get frightened about the amount of informations given; in normal appli-
- cations you will need only a few of them!
- (Start with looking at the example *.PAS files and play around with them
- - you'll learn a whole lot more by first using them as templates than by
- reading manuals!)
-
-
- ABSOLUTE COORDINATES - information
- ──────────────────────────────────
-
- See : coordinates
-
-
- ActualColors - variable
- ───────────────────────
-
- Function : Supplies the actually used palette
-
- Declaration: VAR ActualColors:Palette;
-
- Description: This variable holds the values of the actual graphic colors.
- You can use it to change the palette, but must issue a call to
- SetPalette() to make your changes visible.
- E.g., to make color 5 to "mere green", you would code:
- ActualColors[5].red :=0;
- ActualColors[5].green:=63;
- ActualColors[5].blue :=0;
- SetPalette(ActualColors,TRUE); {or ...,FALSE}
-
- Note : -Whenever you change palette values by using the routine
- SetPalette(), AniVGA reflects the changes in ActualColors, that
- is, as long as you don't work around AniVGA's SetPalette()-
- routine by directly tempering with the VGA's palette registers,
- ActualColors always holds the actual palette (so you won't need
- GetPalette() )
-
- See also : Palette, SetPalette, GetPalette
-
-
- Animate - procedure
- ───────────────────
-
- Function : Performs a complete animation cycle
-
- Declaration: PROCEDURE Animate FAR;
-
- Description: A call to Animate() clears the invisible graphic page by copying
- the contents of the background image into the actual drawing
- page (specified by variable PAGE).
- Then all active sprites (SpriteN[i]<>0) in the visible window
- (determined by StartVirtualX and StartVirtualY) are drawn in the
- style and at the coordinates given by the user.
- After that, the routine waits for the display enable signal to
- reprogram the VGA adapter to flip the display pages, making the
- completed image visible and changes PAGE to point to the new,
- invisible graphic page.
- Finally, the procedure looks how much time passed since the last
- animation cycle and if this time is less than that set by
- SetCycleTime(), the program waits accordingly.
-
- Note : This procedure is the kernel routine which has to be called
- everytime when you have set all data for a new animation frame.
-
- See also : PAGE, SetCycleTime, StartVirtualX, StartVirtualY
-
-
- AniVGAVersion - constant
- ────────────────────────
-
- Function : Holds version number of AniVGA-unit
-
- Declaration: CONST AniVGAVersion=11;
-
- Description: Starting with V1.1, all versions of AniVGA will define this
- constant, holding the version number of the unit.
-
- Note : This constant is new with version 1.1; if for some case you need
- a homogenous scheme for version 1.0, too, then you must add the
- definition "AniVGAVersion=10" to somewhere in the constant decla-
- ration part in the interface section of AniVGA V1.0 and recompile
- that unit!
-
- See also : -
-
-
- BackGndPage - constant
- ──────────────────────
-
- Function : Holds the page number of the backround page
-
- Declaration: CONST BACKGNDPAGE=2;
-
- Description: When using background mode STATIC, BackGndPage specifies the page
- number of the background image for the animations to be used.
-
- Note (!) : Use of this constant only makes sense when using background mode
- STATIC!
-
- See also : ScrollPage, Background
-
-
- Background - information
- ────────────────────────
-
- The term "background" specifies a graphic image in front of which all anima-
- tions take place.
- There are two sorts of background in AniVGA: SCROLLING background and STATIC
- background, which you choose with SetBackgroundMode().
-
- As its name states, a STATIC background cannot be scrolled: it consists of a
- 320x200 pixels picture.
- This background picture is stored in the graphic page numbered BACKGNDPAGE.
- At the very start of every animation cycle, the routine Animate copies that
- picture into the actual drawing page, thus erasing old stuff on that page and
- building the basis for the new image.
- As a normal bitmap picture, it is 320x200=64000 bytes in size. If you use the
- GRAB-Utility or the WritePage()-Routine to save an image, a three byte header
- is put ahead of the information, thus extending the size to 64003 bytes.
-
- The second background sort is called SCROLLING: like AniVGA's virtual coor-
- dinates, you can define a huge background image and scroll over it.
- Unfortunately, it is impossible to hold a complete background picture in
- memory: you would need 32000*32000=1024000000 bytes RAM (!) to do that.
- Instead, AniVGA uses a "tiling" mechanism: tiles are small pictures (16x16
- pixels) which can be combined freely to build the background image.
- You can use up to 256 different tiles and "pin" them on an background area of
- up to MaxTiles (=10000) tiles; everything outside of this background area
- will be assigned to tile no. 0 automatically.
- For example, let us assume that you use only scrolling in the y-coordinate
- axis, 16 screens in total: thus, your x-coordinates reach from 0 to 319 and
- your y-coordinates from 0..(16*200-1)=5119, which gives an area of 320*5120
- =1638400 pixels.
- This is equivalent to (320/16)*(5120/16)=20*320=6400 tiles (remember: each
- tile consists of 16x16 pixels!).
- So you would define the scroll range for the background area needed with
- SetBackgroundScrollRange(0,0,319,5119) and start "painting" your background:
- You could design up to 256 different tiles and use them to assemble your
- background image (=those 6400 tiles).
- Most often, only a few are needed, because the background image isn't that
- dramatically different all over the place. For simplicity, let's assume that
- you need only 16 different tiles, numbered 0..15 respectively in the
- following order to build your background image:
-
- (0,0) (319,0)
- ┌────────┬────────┬────────┐ ┌────────┬────────┬────────┐
- │ │ │ │ │ │ │ │
- │ 0 │ 1 │ 2 │ ... │ 13 │ 14 │ 15 │
- │ │ │ │ │ │ │ │
- ├────────┼────────┼────────┤ ├────────┼────────┼────────┤
- . . . . . .
- . . . . . .
- . . . . . .
- ├────────┼────────┼────────┤ ├────────┼────────┼────────┤
- │ │ │ │ │ │ │ │
- │ 0 │ 1 │ 2 │ ... │ 13 │ 14 │ 15 │
- │ │ │ │ │ │ │ │
- └────────┴────────┴────────┘ └────────┴────────┴────────┘
- (0,5119) (319,5119)
-
- Now all you have to do is to tell AniVGA that layout with the PutTile
- command! You _could_ do so manually:
-
- {assuming SetBackgroundScrollRange(0,0,319,5119) has been set}
- number:=0;
- y:=0; {better: y:=BackY1}
- REPEAT (things would become easier if Pascal would know a STEP-command...)
- x:=0; {better: x:=BackX1}
- REPEAT
- PutTile(x,y,number);
- number:=(number+1) MOD 16;
- inc(x,16);
- UNTIL x>319; {better: x>BackX2}
- inc(y,16);
- UNTIL y>5119; {better: y>BackY2}
-
- That's it! (It is better to use the (global defined) "Back..."-variables,
- set by the former SetBackgroundScrollRange()-call, because AniVGA has to
- adjust values on multiples of 16, see SetBackgroundScrollRange()/Back?? for
- more details). But that's still to complicated: there's a routine called
- MakeTileArea() which does the above job more accurately:
- MakeTileArea(0,16,1) would do the same thing, telling AniVGA to repeat a
- pattern 16 tiles wide, 1 tile high and starting at tile 1 throughout the
- background area.
-
- So then, why should one use STATIC backgrounds after all when there is such
- a powerful instrument like SCROLLING backgrounds?
- There are two simple answers: speed and simplicity! - First, SCROLLING back-
- grounds take a lot of work to compute, which slows down animations (unless
- you have a fast machine, because then the VGA's memory access time becomes
- the limiting factor). Second, it is easy to do some "tricks" on static
- backgrounds:
- draw a line in the static background page and >zap!< starting with the next
- animation cycle, it will be visible for all times. Stated otherwise, when
- using scrolling background, you cannot use drawings to the background image,
- because it simply doesn't exist explicitly, you are restricted solely to
- "tiles" and "sprites"! (On the other hand, you can play nice tricks on
- scrolling background by changing single tiles...)
- So consider carefully what mode you are going to use for your application!
- ___
- Starting with V1.2, things became even more complicated... :-)
- Now, AniVGA knows something called "windowed animations". This simply means
- that in _both_ background modes STATIC and SCROLLING, you are no more
- restricted to use the complete monitor area for animations: there is a new
- routine SetAnimateWindow() with which you can define which part of the screen
- area (0,0)..(XMAX,YMAX) should serve as "stage" for your animations.
- If you use this routine to define a window area ranging from (WinXMIN,WinYMIN)
- to (WinXMAX,WinYMAX), your screen layout becomes this:
-
- _ _ _ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- |1 |
-
- | |
- ╔═══════════════════════╗
- | ║2 ║ |
- ║ ┌──────────┐ ║
- | ║ │3 │ ║ |
- ║ │ │ ║
- | ║ └──────────┘ ║ |
- ║ ║
- | ╚═══════════════════════╝ |
- . .
- . .
- |_ _ _ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
-
- Area 1 is AniVGA's coordinate space, ranging form -16000 to +16000 on each
- axis; area 2 represents your monitor screen: its upper left corner correlates
- to pixel (StartVirtualX,StartVirtualY) of area 1. However, only your
- animation window (=area 3) works as a peephole to area 1, while area
- "2 minus 3" is filled with the contents of the background page.
- By default, area 2 = area 3, but if you want, you can shrink area 3 to
- whatever you want (nearly..) and set up some fancy graphics in area 2.
- Your animations won't "bleed out" into area 2: neither your sprites nor your
- background tiles or whatever!
- (BTW: yes, this works with background mode SCROLLING, too. That means, that
- with SCROLLING backgrounds, *both* background pages (BACKGNDPAGE _and_
- SCROLLPAGE) will be used: the former for area 2, the latter for for area3.
- Note however that AniVGA won't care for the non-window area 2! If you draw
- something to this area (for example, by using BackgroundOutTextXY() or the
- other pixel drwaing routines), you MUST trigger a mechanism to make these
- changes visible, for example by the sequence "UpdateOuterArea:=2; Animate"!)
-
- See also : BACKGNDPAGE, BACKGNDADR, WritePage, LoadPage,
- WriteBackgroundPage, LoadBackgroundPage, SetBackgroundMode,
- LoadTile, Tile, SetAnimateWindow
-
-
- BackgroundGetPixel - function
- ─────────────────────────────
-
- Function : Reads a background pixel's color
-
- Declaration: FUNCTION BackgroundGetPixel(x,y:INTEGER):BYTE; FAR;
-
- Description: This routine will return the color value of the specified point
- with virtual coordinates (x,y) in the background image.
- If the corresponding absolute coordinates lie outside the screen,
- zero (= black) will be returned.
-
- Note (!) : - Use of this routine works only when using background mode
- STATIC! It might look strange to use virtual coordinates then,
- although the background is said to be static (= non-scrollable)
- and hence restricted to absolute coordinates anyway, but it is
- often convenient to use an uniform notation and it is easy to
- convert coordinates accordingly (see "coordinates" for more
- about that).
- - If you are using EMS, ensure the presence of the right EMS-
- memory block by a
- "IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)"
- statement!
-
- See also : coordinates, GetPixel, PageGetPixel, EMS
-
-
- BackgroundLine - procedure
- ──────────────────────────
-
- Function : Draws a line on the background page
-
- Declaration: PROCEDURE BackgroundLine(x1,y1,x2,y2:INTEGER); FAR;
-
- Description: To draw a line on the background page (thus alterating the back-
- ground), you can use this procedure. Like the similiar Line()-
- routine, it uses virtual coordinates, too.
- If necessary, the line will be clipped down to its visible part
- (using a special Sutherland-Cohen algorithm).
-
- Note : - Use of this routine only makes sense when using background
- mode STATIC!
- - An exception from this rule: if you use an animation window
- _and_ SCROLLING mode, then the non-animation-window-area is
- covered with the background image from page BACKGNDPAGE, so
- you may use this routine (and all similiar pixel drawing
- routines like BackgroundPixel() etc.).
- If you use the routine for drawing to this area, you MUST
- use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
- to make these outer area changes visible!
-
- See also : Line, coordinates
-
-
- BackGroundMode - variable
- ─────────────────────────
-
- Function : Holds the actual choosen background mode
-
- Declaration: VAR BackgroundMode:BYTE;
-
- Description: Using SetBackgroundMode(), you can select one of the possible
- background modes STATIC or SCROLLING. BackGroundMode stores this
- value.
-
- Note (!) : Only read this value, never change it directly!
-
- See also : Background, SetBackgroundMode
-
-
- BackgroundOutTextXY - procedure
- ───────────────────────────────
-
- Function : Writes a textstring to the background page BACKGNDPAGE
-
- Declaration: PROCEDURE BackgroundOutTextXY(x,y:INTEGER; s:STRING); FAR;
-
- Description: This routine is exactly the same like OutTextXY() (see there), but
- it writes the string into the background page (so it will be visi-
- ble permanently).
-
- Note(!) : - Use of the routine only makes sense if STATIC is used as
- background mode. With SCROLLING backgrounds, use OutTextXY()
- instead.
- - An exception from this rule: if you use an animation window
- _and_ SCROLLING mode, then the non-animation-window-area is
- covered with the background image from page BACKGNDPAGE, so
- you may use this routine (and all similiar pixel drawing
- routines like BackgroundPixel() etc.).
- If you use the routine for drawing to this area, you MUST
- use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
- to make these outer area changes visible!
-
- See also : GraphtextColor, GraphtextOrientation, GraphtextBackground,
- OutTextXY, background
-
-
- BackgroundPutPixel - procedure
- ──────────────────────────────
-
- Function : Plots a point into the background page
-
- Declaration: PROCEDURE BackgroundPutPixel(x,y:INTEGER; color:BYTE); FAR;
-
- Description: (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its _absolute_
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- background page BACKGNDPAGE (and become visible starting with the
- next animation cycle).
-
- Note (!) : - Use of this routine makes sense only when using background mode
- STATIC!
- - An exception from this rule: if you use an animation window
- _and_ SCROLLING mode, then the non-animation-window-area is
- covered with the background image from page BACKGNDPAGE, so
- you may use this routine (and all similiar pixel drawing
- routines like BackgroundPixel() etc.).
- If you use the routine for drawing to this area, you MUST
- use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
- to make these outer area changes visible!
- - This routine works with virtual coordinates! - Although this
- seems silly at first glance (because in STATIC mode, background
- coordinates are always restricted to (0,0)..(319,199)), it
- appears to be handy in many situations. If you actually want to
- address points absolute coordinates (a,b), you can call this
- routine with coordinates (a+StartVirtualX,b+StartVirtualY)
- instead.
- - Because of AniVGA's working scheme, you probably want to call
- this routine _before_ calling Animate(), so that changes of the
- point will be visible as soon as possible.
- - If you are using EMS, ensure the presence of the right EMS-
- memory block by a
- "IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)"
- statement!
-
- See also : PutPixel, PagePutPixel, background, coordinates, EMS,
- How AniVGA works
-
-
- BACKX1, BACKX2, BACKY1, BACKY2 - variables
- ──────────────────────────────────────────
-
- Function : Hold the background image boundaries in background mode SCROLLING
-
- Declaration: BackX1,BackY1,BackX2,BackY2:INTEGER;
-
- Description: When background mode SCROLLING is to be used, you have to define
- a scrolling area (with SetBackgroundScrollRange()). Due to inter-
- nal management restrictions of AniVGA, the boundaries of this area
- must fall on coordinates which are multiples of 16 ("on a grid
- with mesh 16").
- If the values you supply don't fulfill this restriction, AniVGA
- adjusts them automatically to do so and stores them to these
- variables for further use.
-
- Note : The only reason these variables are visible to you are that it
- could be necessary for you to notice adjustments AniVGA did;
- so: only read this values, never change them directly!
- (Look at "background" for an example).
-
- See also : background
-
-
- BFFFFFFF - utility
- ──────────────────
-
- Ever had a flat tire? It makes "bffffffffff" as the air goes out and the tire
- becomes smaller and smaller...
- BFFFFFFF is a little compression utility which "lets the air out of your data
- files". Unlike a flat tire, your data files remain functional, however: AniVGA
- has been extended to use some disk reading routines which are "transparent" to
- compressed FNT-, PIC-, PAL-, COD- and LIB-files in that it notes whether the
- file to read in has been compressed with BFFFFFFF or not and acts accordingly.
- You have to supply three command line parameters:
- - the source file name,
- - the destination file name (which must be different from the source)
- - and if you want to (c)ompress or (d)ecompress your file.
- For example...
-
- BFFFFFFF mysprite.lib mysprite.new c
-
- ...would compress the file mysprite.lib to the file mysprite.new! You could
- now delete the old mysprite.lib file and rename mysprite.new to mysprite.lib,
- if you want.
-
- If you want to create a compressed library, you have several possibilities:
- a) First compress the COD-files and then concatenate them to the LIB-file
- b) First concatenate the (uncompressed) COD-files and then compress this LIB
- c) Concatenate some compressed and not compressed files together to form a
- library (but you may *NOT* compress that library afterwards!!!)
- d) Build two compressed libraries, using a),b) or c), and then concatenate
- them to form a new library
- In other words, you may concatenate and/or compress freely, as long as you
- meet one requirement: no file may be compressed more than one time!
- In especially, you may not compress a LIB-file in which one or more COD-files
- have already been compressed beforehand!!!
-
- The most effective way for compression is b): chain uncompressed COD-files to
- build a library and then compress that library. If you are unsure whether one
- or more of the files within that library have already been compressed in
- before, then use UNLIB on the library (this will result in uncompressed CODs),
- bundle these files again to form a library and then compress it.
-
- Note : - Using compressed files is a trade off between speed and disk space:
- compressed files take some time to decompress while loading, but pre-
- serve disk space, uncompressed files load faster but occupy more disk
- space.
- - First, create your program with uncompressed data files. Then, decide
- if it pays of to compress the files.
- - All utility files with the exception of BFFFFFFF will produce uncom-
- pressed data files; you'll have to use BFFFFFFF to compress them.
- - As said, you may not "double compress" a file; however, BFFFFFFF can
- care for that automatically with the exception of LIBs (see above)
- - If you type in the command line to invoke BFFFFFFF, don't count the
- "F"s, as MSDos will forgive you, if you type in more than necessary:
- BFFFFFFFFFFFFFFFFFF foobar.cod foobar.new c will work, too!
- - See "COMPRESS" below for more information about the compression
-
-
- COMPRESS - unit
- ───────────────
-
- Function : Provide data compression and decompression routines
-
- Declaration: Unit Compression;
-
- Description: AniVGA has been extended to use compression techniques for data
- storage (COD-, FNT-, LIB-, PIC- and PAL-files). "Compression" is
- the unit which holds the necessary code to achieve this; techni-
- cally spoken, it's an implementation of a combined RLE and
- Huffman algorithm.
- All data access routines are "transparent" in that they automati-
- cally detect whether the data file to read in has been compressed
- or not and act accordingly.
- This way, it is up to you to decide whether you want to use data
- compression with your program (which slows down reading in the
- files but preserves disk space) or not.
- In my opinion, it is best to first develop your program normally
- and then afterwards decide _if_ and _which_ files to compress.
- Compression itself has to be done manually by using BFFFFFFF on
- the files (see there for more information).
-
- Note : - COMPRESS can be used as a stand-alone unit for data compression
- purposes, of course. Read COMPRESS.DOC for more about that
- - It is easy to find out, whether a file has been compressed or
- not: just look at the very first bytes in the file; if they
- read "HUC" (for: Huffman coded), then it is compressed
-
- See also : BFFFFFFF
-
- CopyVRAMtoVRAM - procedure
- ──────────────────────────
-
- Function : Copy video RAM contents using write mode 1
-
- Declaration: PROCEDURE CopyVRAMtoVRAM(source,dest:POINTER; len:WORD); FAR;
-
- Description: This is a generic low-level procedure to move video data around.
- It uses write mode 1 of the VGA card for quick video memory
- moves and awaits the source and destination addresses in
- "source" and "dest", respectively. "len" is the length of the
- block to move in _address bytes_ (in write mode 1, one address
- bytes stands for four memory bytes).
-
- Note : - It became necessary merely for one reason: as the background
- page has been moved from VRAM to normal RAM (or EMS), commands
- to load "the background page" now route their data to RAM.
- To access the *VRAM* area formerly assigned to that page (in
- the address range $A000:$7D00..$A000:$BB7F), you first have to
- load data into page 0 or 1 and then move it to that area using
- CopyVRAMtoVRAM(Ptr($A000,0),Ptr($A000,$7D00),PAGESIZE).
- This way, that area can be used for storing a picture,
- presumably for use of IntroScroll()
- - Because write mode 1 is used, the addresses must lie in the
- VGA's card address range. On normal VGA-cards, this is the
- $A000 segment only; some SVGA-cards also enable the $B000
- for graphic usage, but don't rely upon that!
- - This routine is "the hacker's toolkit". You are discouraged
- to use it; maybe it won't be supported in future versions or
- its interface will change.
-
- See also : IntroScroll
-
-
- CloseRoutines - procedure
- ─────────────────────────
-
- Function : Terminates AniVGA
-
- Declaration: PROCEDURE CloseRoutines; FAR;
-
- Description: Calling this routine switches back from AniVGA's special graphic
- mode into the graphic or text mode previously set.
-
- Note : This should always be the last call to a routine of AniVGA in your
- programs.
-
- See also : InitGraph
-
-
- COLLISION-DETECTION, CONCAVE, CONVEX - information
- ──────────────────────────────────────────────────
-
- A graphical figure can be classified by its outline into one of two groups,
- called "concave" or "convex" figures.
- To motivate this mathematical notion >eh, don't get frustrated...<, regard
- your sprite only given by its "outmost" points, which connected together shape
- the figures boundaries.
- The figure is called "convex" :<=> every pair of arbitrarily choosen points
- on this boundary build a line which is totally inside (or at least on the
- boundary of) the figure:
- ┌──────┐ This rectangle is "convex", because whenever you choose two points
- │ │ on its boundaries and connect them, the resulting line lies com-
- └──────┘ pletely inside (or on the boundary) of the rectangle itself.
-
- ┌──────┐ On the other hand, this figure would be "concave", because if you
- └─┐ ┌─┘ choose the top-right and bottom-right corner (say) and connect them,
- ┌─┘ └─┐ then the middle part of the resulting vertical line lies outside the
- └──────┘ figure.
-
- That is (in a very lax form) the _mathematical_ definition of these terms, but
- AniVGA completely deals with either horizontal or vertical lines, so that an
- extension of these terms can be made:
-
- A sprite is called "horizontal concave" ("vertical concave"), if a horizontal
- (vertical) line connecting two points of the sprite's boundary can be found
- so that parts of this line lies outside the sprite; if the sprite is not hori-
- zontal (vertical concave), it is "horizontal convex" ("vertical convex").
-
- In that sense, the second of the figures above is "vertical concave", but
- "horizontal convex"!
- (Notice that figures which are concave in the pure _mathematical_ sense are
- sometimes treated as convex by this definition, as this cross:)
- ┌─┐ (If you use either a horizontal or vertical "scan line" sweeping
- ┌─┘ └─┐ throughout the cross, there will be never more than one part of
- └─┐ ┌─┘ the "scan line" which belongs to the figure; you can use this
- └─┘ principle as a second definition for horizontal/vertical convex)
-
- This terminology comes in handy when describing some mechanisms of AniVGA: a
- sprite is drawn LINEwise. For this, every point between the leftmost and right-
- most point of a sprite's line is considered to be an _inner_ point of the
- sprite, thus AniVGA assumes a horizontal convexity! If your sprite isn't, like
- this one...
- ┌─────┐ ...and the points between the two "legs" of this sprite shall still
- │ ┌─┐ │ be treated as "transparent" (assuming they have been defined with
- │ │ │ │ color "black" (=0)), you must use display mode "Display_NORMAL",
- │ │ │ │ because the "Display_FAST" mode would treat them as belonging to the
- └─┘ └─┘ sprite itself and draw them as "covering" black.
-
- (To state it otherwise: whenever your sprite is (at least) horizontal convex
- and you don't need the feature of transparent parts inside the sprite, you
- can use the "Display_FAST" mode without any loss of accuracy in the sprite
- display)
-
- Tip: the spritemaker program MAKES allows to display a sprite's horizontal
- boundaries, which makes it easier for the beginner to decide about that
- figure's convexity. But whenever you are unsure, you still can use mode
- "Display_NORMAL" for drawing it.
-
- ---
-
- Things get a bit more tough when deciding if two sprites collide or not (which
- is an important task): in difference to many sprite toolkits, AniVGA doesn't
- use a "mask" approach, which makes sprites big and collision detection slow.
- Instead, AniVGA uses a sprite's outline to decide whether two sprites collide.
- For that, it computes for every line (column) of the overlap region of the
- sprites' surrounding rectangles, whether the sprites overlap horizontally
- (vertically) and says "collision!" only if there are intersections in both
- directions. In pseudo code:
-
- IF smallest_box_around(sprite1) doesn't intersect smallest_box_around(sprite2)
- THEN no_collision
- ELSE BEGIN
- compute the lines and columns for which the 2 sprite rectangles overlap
- FOR every such line compare -with the help of the sprite boundaries- if
- the corresponding lines overlap
- FOR every such column do the same check
- ONLY_IF there is an intersection in at least one line AND one column
- THEN collision!
- ELSE no_collision
- END
-
- If you think a byte (=8 bits...) about this algorithm, you'll see that it can
- lead to misdetection, in that the algorithm says "collision!", although there
- is none (but it still guarantees that if there _is_ a collision, the alg. will
- detect it) as in the following example:
- ┌─────┐
- └───┐ │
- ┌────────┐ │ │
- │ ┌────┐ │ │ │
- │ │ ┌─┐│ │ │ │ <─ In this line there is a "horizontal collision" (that is,
- └─┘ │ │└─┘ │ │ the two sprites overlap in their horizontal dimension)
- │ └────┘ │
- └────────┘ ┌─ In this column there is a "vertical collision"
- ^───────┘
-
- To state things without a proof here, such an (unavoidable) misdetection is
- only possible, if at least one of the two sprites is neither horizontal nor
- vertical convex!!!
-
- Even then, it takes special constellations (as the one above) to produce such
- an error, so that in praxis, it is very unlikely for such an error to occur.
-
-
- Color - variable
- ────────────────
-
- Function : Determines the actual drawing color
-
- Declaration: VAR Color:BYTE;
-
- Description: Various drawing routines use this global variable to determine
- which color should be used.
-
- Note : AniVGA uses the standard color table of the 256-color mode $13.
-
- See also : -
-
-
- ColorTable - type
- ─────────────────
-
- Function : Supply a data type for self-defined "Shadow Tables"
-
- Declaration: TYPE ColorTable=ARRAY[0..255] OF BYTE;
-
- Description: If you want to use a different color look-up-table for your
- sprites in display mode Display_SHADOW or Display_SHADOWEXACT
- than can be achieved with SetShadowTab(), you must build a table
- like this.
- Each entry gives the color which should be used to replace the
- original color with that index, i.e.: if c is of type ColorTable
- and c[5]=9, this means that every point of your sprite which is to
- be drawn over a pixel with color 5 should replace that pixel with
- color 9.
- You can find an example how to activate such a "home-brew" table
- at "ShadowTab".
-
- Note : -
-
- See also : ShadowTab, SetShadowTab, Display modes, Palette
-
-
- COORDINATES - information
- ─────────────────────────
-
- AniVGA has to deal with two kinds of coordinates: "virtual" and "absolute" ones.
- An absolute coordinate lies in the range 0..319, 0..199 for the x and y values,
- respectively. It names a unique point on your graphic screen.
- However, AniVGA doesn't restrict animations to take place on the visible
- graphic screen: its routines deal with coordinates in the range -16000..+16000
- in each direction, called "virtual coordinates".
- The picture you view while AniVGA's routines are running is a window of that
- virtual screen, 320 points wide and 200 points high.
- Naturally, the graphic hardware only knows absolute coordinates and thus,
- AniVGA has to transform virtual in absolute coordinates. It does this with the
- help of the two variables StartVirtualX and StartVirtualY which together speci-
- fy the starting point of the upper left corner of your actual screen window;
- e.g. if (StartVirtualX,StartVirtualY) was (1000,2000) then you would look at
- the part of AniVGA's world which consists of the 320x200 region with the coor-
- dinates xε(1000..1319) and yε(2000..2199).
- Note that there is one severe restriction, though: because it is absolutely
- impossible to hold a complete "virtual" screen bitmap for AniVGA's world in
- memory (it would need app. 1GB RAM!), all drawing commands only take place on
- the visible screen.
- This means that you can't draw lines, points or any other objects which are
- _not_ sprites outside the visible window that become visible, when you scroll
- your window over to that part of the virtual screen. For example, if you draw
- a point somewhere outside your visible window (say at (-10000,1234) while your
- visible window starts at (500,900)) and pan to that region afterwards (by set-
- ting (StartVirtualX,StartVirtualY)=(-10100,1200) or something like that), you
- won't see that point: it is stored nowhere.
- (The only way to circumvent this is to define the point as a sprite and set its
- coordinates (SpriteX[],SpriteY[]) to (-10000,1234), because sprites are the
- only objects which the system stores!).
-
- More general:
- Because there is _no_ complete virtual screen, all information drawn outside
- the coordinate range visible at the moment will be lost and all information
- read in from these "offscreen" pixel positions will be zero (= black).
- For that reason it may seem strange for some routines that were restricted in
- their use to the "real" (= absolute coordinate) screen region to use virtual
- coordinates inspite (e.g.: GetImage, BackGroundGetPixel,...), but this was done
- intentionally, because it leaves room for further improvements: if it should be
- possible some day to store a complete virtual screen image, there will be no
- changes necessary in AniVGA's syntax.
- Meanwhile, it is simple to transform absolute and virtual coordinates into each
- other whenever necessary, using the following equivalence:
-
- virtual X-coordinates - StartVirtualX = absolute X-coordinates
- virtual Y-coordinates - StartVirtualY = absolute Y-coordinates
-
- As a result: virtual coordinates lie in the range -16000..+16000, the start of
- the visible part is defined in StartVirtualX and StartVirtualY and only sprites
- can be "scrolled in" into the visible screen, while all other objects are
- "lost".
-
-
- DefaultColors - constant
- ────────────────────────
-
- Function : Supplies the default RGB-colors of mode $13 to the user
-
- Declaration: CONST DefaultColors:Palette=
- (
- (red: 0; green: 0; blue: 0),
- [...stuff deleted...]
- (red: 63; green: 63; blue: 63)
- );
-
- Description: AniVGA and its accompanying utility programs are based on the
- Bios' default color palette. That ain't necessary, though (and
- you *can* set different palettes), but it makes things a bit
- easier!
- DefaultColors is a listing of these default colors.
-
- Note : Consider the table as *read only*! When you use SetPalette(),
- AniVGA will not temper this table (thus you can use it to restore
- the original palette values again).
-
- See also : Palette, SetPalette, GetPalette
-
-
- Display modes - information
- ───────────────────────────
-
- AniVGA is able to display a sprite in several "modes". This describes how the
- sprite's data should be handled when drawing the sprite to the screen. Up to
- now, there are four modes:
- - Display_NORMAL
- - Display_FAST
- - Display_SHADOW
- - Display_SHADOWEXACT
- This mode is linked to a sprite's physical data by creation of the sprite with
- the spritemaker program (and defaults to Display_NORMAL), but can be altered
- once the sprite is loaded into memory with the procedure SetModeByte().
-
- Note that the display mode information is part of the _physical_ sprites (that
- is, the memory image of the bytes loaded at the beginning), not the _logical_
- sprites (the "handles" in the SpriteN-array to this physical data). For that
- reason, a change of the display mode of a sprite with spriteLOAD number 123
- (say) will affect _all_ sprites of type 123 (= all entries in SpriteN[] with
- value 123). This is intended, because the display mode is a piece of informa-
- tion reflecting the sprite's physical structure!
- (For the case that you disagree: of course you are free to load the same sprite
- with a different load number into memory a second time and assign another
- display mode to this copy!)
-
- In mode "Display_NORMAL" you can think of a sprite as a picture with holes at
- the places where its pixels have color 0: when displayed, all the parts of the
- sprite with color<>0 will cover (paint over) the screens original pixels, but
- the pieces with color=0 will act like "window panes": the original contents of
- the screen remain visible there.
- This mode is useful for all kinds of sprites which have such opaque holes in-
- side themselves: cars/planes/houses or other objects with window panes, but
- also all "concave" sprites. Note that black, COVERING parts must be realized
- with a dark color<>0, for example color 16.
-
- "Display_FAST" is a bit (but not that dramtically) faster than the last method,
- because it doesn't know of a special color: all sprite data is treated equally
- and stored to the screen at once. For that, all parts of the sprite are
- covering. (But note that a sprite consists only of the points "inside" and on
- its boundaries: all the points "outside" the sprite doesn't matter).
- You will use this mode whenever you have sprites which meet the following re-
- quirements: they are "convex" and don't have any transparent parts inside them-
- selves.
-
- "Display_SHADOW" is a tribute to the fact that one often needs some kind of
- shadowing to give the impression of an freefloating object or other pseudo
- 3D-effects. In this mode, the sprite's real colors are insignificant, only its
- boundaries and the actual contents of the screen where the sprite shall be
- drawn are important. The color of every sprite point is determined by the color
- of the appropriate screen point. The color of these points are translated by
- the lookup table ShadowTab into darker ones.
- If you want to give a sprite a shadow zone, then you must divide your sprite
- into two ones: one building the sprite itself and a second one to realize only
- that shadow area, and compose them with appropriate coordinates.
-
- "Display_SHADOWEXACT" behaves quite similiar to "Display_SHADOW", but shadowing
- will only take place at the sprite's pixels with color <>0, that is: color 0
- is again used as "transparent", this time even for shadows! To state it other-
- wise: Display_SHADOWEXACT is for displaying shadows what Display_NORMAL is for
- displaying sprites (and Display_SHADOW relates to Display_FAST in that sense):
- exactly for the same reason, Display_SHADOWEXACT is slower than Display_SHADOW!
- Normally, you will use Display_SHADOW when you are using Display_FAST, too: If
- your sprites are "convex" and don't have any transparent parts inside them-
- selves.
- (If you are still not sure about the difference between these two combinations
- a) Display_FAST & Display_SHADOW
- b) Display_NORMAL & Display_SHADOWEXACT
- then EXAMPLE3.PAS is a good place to try out!)
-
- Technically spoken, there are short code areas in AniVGA's routines reserved in
- which the right piece of code to transfer/interpret the sprite's data become
- copied, when not already there. For optimal performance it is wise to group the
- entries in SpriteN[] such that adjacent sprite entries share the same display
- method.
-
- See also : convex, concave
-
-
- DUMP_SPR - utility
- ──────────────────
-
- (This is surely a tool for all those hackers among us...)
- If you want to take a closer look at a sprite's data, you don't have to fiddle
- around with DEBUG or the like, just use this sprite dumper: it takes a (binary)
- sprite file (*.COD or *.LIB) and disassembles it into readable ASCII-text.
- You can redirect the output to a file or printer, e.g.:
-
- DUMP_SPR mysprite.cod >mysprite.txt
-
- would dump the sprite file "mysprite.cod" to the ASCII-text file "mysprite.txt"
- for further usage.
- Note that DUMP_SPR creates a format which will be understood by assemblers like
- MASM or TASM so that you can reassemble the files to get a binary sprite file
- once again!
- To do so, you would have to enter the following commands (replace MASM by TASM
- if you use Borland's assembler):
- MASM mysprite.TXT; -> gives you mysprite.OBJ
- LINK mysprite.OBJ; -> gives you mysprite.EXE
- EXE2BIN mysprite.EXE mysprite.COD -> gives you mysprite.COD
-
-
- EMS - information
- ─────────────────
-
- Declarations:
-
- Const EMSInt = $67; {this is the INT used for the EMS routines}
- USEEMS = TRUE; {setting this value to FALSE will prevent AniVGA from }
- {using EMS; if you set it to TRUE, it will use EMS if }
- {at least 64K are available and its "true" (=hardware)}
- {EMS. Otherwise, AniVGA switches to normal RAM auto- }
- {matically}
- Var EMSError:BYTE; {Any error occuring during a EMS call is reflected by }
- {this variable exactly. Of course, the more simple "go}
- {no-go" result of any routine using EMS is reflected }
- {in the "Error", too!}
- BackgroundEMSHandle:WORD; {this is the handle to the allocated EMS block}
- EMSused:BOOLEAN; {reflects, if AniVGA really uses EMS: if for some }
- {reason AniVGA denied to use EMS inspite of USEEMS = }
- {TRUE, this variable will be set to FALSE}
- PROCEDURE EnsureEMSConsistency(EMSHandle:WORD);
- {this is the routine to bring in the named EMS block into the EMS page frame}
-
-
- Starting with V1.2, the background page has been moved from video memory to
- normal RAM (this results in speed gains on most VGA cards which are unbelie-
- vably slow when accessing VRAM).
- To cut down memory requirements, AniVGA uses 64K EMS memory, if available.
- Now it is possible that you do use EMS memory on your own and therefore some
- precautions have to be taken to avoid interference of the routines. Most of
- them will be handled by AniVGA automatically, but a few remain to your
- responsibility.
- If you already know about how EMS works, just skip the following paragraph:
-
- EMS is the idea to provide additional memory through an address window of 64K
- (called the "page frame") in a normally unused address space, typically
- $C800:0..$C800:$FFFF or something similiar. A device driver is needed for
- handling EMS and the routines are linked into your system via INT $67.
- These routines are necessary, because if you have 2M (say) of EMS, you must
- tell the hardware somwhow, _which_ 64K out of those 2M shall be "visible" in
- the page frame right now! For this, EMS manages its RAM by so-called "EMS-
- handles": if you allocate an EMS memory block, you get such a handle in
- return. Now each time your software wants to access "its" EMS-memory, it has
- to make sure that this EMS-block is mapped into the page frame --and it does
- so by naming the handle to the EMS-memory.
-
- It would be pretty easy to ensure the consistency of what we *want* to see
- inside the EMS page frame with what *is* inside it by simply issuing a
- "MapEMSBlockIntoFrame(EMSHandle)"-like command, each time before we start
- accessing any memory cell of the page frame.
- Translated to AniVGA's needs (where only the BACKGNDPAGE's contents have been
- moved to EMS), it would suffice to issue something like...
- IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle)
- ...whenever we are going to access the background page.
- However, there are situations where this would be a waste of computer
- resources:
- FOR i:=1 TO 10000 DO
- BEGIN
- IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle);
- PagePutPixel(Random(XMAX+1),Random(YMAX+1),Random(256),BACKGNDPAGE)
- END;
-
- Obviously, ensuring the EMS consistency _once_ is enough, as the rest of the
- loop does not change the EMS frame allocation:
- IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle);
- FOR i:=1 TO 10000 DO
- BEGIN
- PagePutPixel(Random(XMAX+1),Random(YMAX+1),Random(256),BACKGNDPAGE)
- END;
-
- Its for this reason only that the above call to EnsureEMSConsistency()
- doesn't have been moved to the BackgroundPutPixel() and BackgroundGetPixel()
- routines! (All the other routines accessing the background page do this
- automatically, as the overhead of the call doesn't matter much, anyway).
-
- Stated otherwise:
-
- !! WHENEVER YOU ARE GOING TO USE Background{Put|Get}Pixel()_AND_ YOU HAVE
- !! REASON THAT THE EMS-PAGEFRAME NEEDS UPDATING, ISSUE THE COMMAND
- !! "IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle)" FIRST!
-
- See also : BackgroundGetPixel, BackgroundPutPixel
-
-
- EnsureEMSConsistency - procedure
- ────────────────────────────────
-
- Function : Brings the contents of the named EMS memory block into the EMS
- page frame
-
- Declaration: PROCEDURE EnsureEMSConsistency(EMSHandle:WORD); FAR;
-
- Description: The routine calls the EMS handler to assure that the EMS memory
- block pointed to by the given handle is placed into the EMS
- page frame.
-
- Note (!) : - A direct call to this routine will be necessary only for the
- BackgroundGetPixel() and BackgroundPutPixel() routines
- - Don't call the routine if you are _not_ using EMS! Use a
- statement like...
- IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)
-
- See also : EMS
-
-
- ERROR - variable
- ────────────────
-
- Function : Holds the code of the last error which occured
-
- Declaration: VAR ERROR:BYTE
-
- Description: If an error occurs while executing one of its routines, AniVGA
- terminates that routine and sets ERROR accordingly to reflect that
- error.
- You can use GetErrorMessage() anytime to get more information,
- which error occured.
- It is your responsibility to check if such an error occured and
- react in an appropriate way.
- For the possible values and their descriptions returned by
- GetErrorMessage, see there.
-
- Note (!) : - After processing an error, you have to reset the variable back
- to Err_None yourself
- - In respect of future extensions, you should treat every value
- <> Err_None as an error
- - The most frequented routine Animate() doesn't produce any
- errors, neither do several other procedures. As a basic rule,
- all routines which have to do with file I/O have to be checked.
- - ERROR is initialized with Err_None
-
- See also : GetErrorMessage, InitRoutines
-
-
- FadeIn - procedure
- ──────────────────
-
- Function : Fade in a graphic page onto the actually visible page.
-
- Declaration: PROCEDURE FadeIn(pa,ti,style:WORD); FAR;
-
- Description: If you need an interesting opening sequence for your program, then
- FadeIn() is what you need: there are a lot of different routines
- available to copy one image to the actually displayed graphic page
- (1-PAGE): supply the page which shall be displayed "pa" (most
- often, this will be BACKGNDPAGE), "ti" is the time (in millise-
- conds) the fade should last (approximately), "style" defines the
- algorithm to be used and must be one of:
- Fade_Squares,
- Fade_Circles,
- Fade_Moiree1 .. Fade_Moiree15,
- Fade_SweepInFromTop, Fade_SweepInFromBottom,
- Fade_SweepInFromLeft, Fade_SweepInFromRight,
- Fade_ScrollInFromTop, Fade_ScrollInFromBottom,
- Fade_ScrollInFromLeft, Fade_ScrollInFromRight
-
- Note : - The easiest way to use this routine is the following:
- a) initialize the graphic mode via InitGraph(),
- b) load the background page BACKGNDPAGE with your normal
- animation background,
- c) (if you want:) fill the visible page 1-PAGE with whatever
- you want (initially, it is completely black)
- d) call FadeIn(BACKGNDPAGE,2000,Fade_???);
- (about 2000..4000 milliseconds are good values)
- e) continue with your normal program
- - Naturally, AniVGA can't make your PC faster than it is: the
- time value you supply is a _lower bound_!
- - FadeIn() will use the "normal" MSDos-timer values for its
- operation; as this timer has resolution of about 55msec, it
- is quite inaccurate (..for a computer, I mean..), but as we
- are talking about thousands of milliseconds here, that won't
- matter! (Besides that, this timer won't interfere with the
- one used for the animation rate, set by SetCycleTime()!)
-
- See also : -
-
-
- FadeToPalette - procedure
- ─────────────────────────
-
- Function : Fades the screen from the actual color to another palette
-
- Declaration: PROCEDURE FadeToPalette(destPal:Palette; AnzSteps:WORD); FAR;
-
- Description: You have often seen that: a screen becomes slowly dark and when
- it returns, another image is displayed. This and other effects
- can be generated by fading a palette to another.
- "destPal" is the destination palette to which the program will
- fade (and "ActualColors" holds the starting colors, of course).
- "AnzSteps" is the number of steps which the routine will
- generate between the color values of the two palettes.
- On return, "ActualColors" ( = the actually displayed color
- palette) has been set to "destPal".
- For example, a sequence like the following
-
- oldPal:=ActualColors;
- FillChar(tempPal,SizeOf(tempPal),0);
- FadeToPalette(tempPal,200);
- [...]
- FadeToPalette(oldPal,200);
-
- would fade the actual screen display to black and afterwards
- fade it back to the previously set colors again.
-
- Note : - Each incremental change of the palette will be synchronized
- to the vertical retrace signal of the VGA card. This way,
- "snowy" displays are avoided. As a side effect, each such
- step takes app. 1/70 sec. In the example above, the fades
- would take 200/70 sec, each.
-
- See also : ActualColors, SetPalette, FadeIn
-
-
-
- FillBackground - procedure
- ──────────────────────────
-
- Function : Fills the background page with the specified color.
-
- Declaration: PROCEDURE FillBackground(color:BYTE); FAR;
-
- Description: The given value is written into the whole graphic page BACKGNDPAGE
- and thus defines the picture before all animations take place to
- have one color.
-
- Note : Use of this routine only makes sense when using background mode
- STATIC!
-
- See also : Background, BACKGNDPAGE, BACKGNDADR, GetBackgroundFromPage,
- LoadBackgroundPage
-
-
- FillPage - procedure
- ────────────────────
-
- Function : Fills a graphic page completely with a given color
-
- Declaration: PROCEDURE FillPage(pa:WORD; color:Byte); FAR;
-
- Description: If you want to paint a complete page uniformly with one color,
- then this will be the fastest method to do it: specify the graphic
- page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE (=3)) in "pa" and the
- color to be used in "color".
-
- Note : - Although possible, you are strongly discouraged to use this pro-
- cedure in background mode SCROLLING (i.e.: pa=SCROLLPAGE (=3) as
- page number), because the background is treated completely dif-
- ferent!
- - Remember also that changes to one of the drawing pages (0 or 1)
- have to be applied _after_ calling Animate and will be visible
- for exactly one animation cycle, whereas changes to the back-
- ground page remain permanent (and are best done _before_ calling
- Animate, although that's not peremptory).
- - This routine is great to produce "flashing" screens: apply it to
- 1-PAGE (the visible page).
- - Possible ERROR-value returned is Err_InvalidPageNumber
-
- See also : background, How AniVGA works, LoadPage, LoadBackgroundPage,
- GetBackgroundFromPage
-
-
- FindFile - function
- ───────────────────
-
- Function : Completes the path-part of a given file name
-
- Declaration: FUNCTION FindFile(P:PathStr):PathStr; FAR;
-
- Description: This routine expects a normal MSDos file name and looks if there
- exists a file with this name. If not, all subdirectories under
- the specified directory are scanned through recursively. If the
- file still can't be located by that search, the empty string will
- be returned as the result, otherwise the extended path name of
- the file is returned.
- For example, if you P = "C:\TEST\MY_FONT.FON", but the correct
- directory would be "C:\TEST\FONTS\MY_FONT.FON", then the routine
- will return the latter path as the result.
- This routine is handy when loading data files: if your users
- forget to create a proper subdirectory structure and copy all
- files into one directory (say C:\ABC\ instead of C:\ABC\BIN\,
- C:\ABC\FONTS\ and C:\ABC\GRAPHIC\), then your program will still
- run if it loads its files by only referencing the top level dir:
- C:\ABC\file.ext will locate the file, no matter in which subdir
- it really is.
-
- Note : - You don't have to use this routine for any of AniVGA's Load* -
- routines: they use FindFile() automatically! (The routine has
- been moved to the interface section of the unit, because it
- may be useful for locating other files, too)
- - In the Load* - routines of AniVGA, the function is used in that
- way: first, the file is searched under the given name; if it
- couldn't be found, all subdirectories of the specified dir are
- scanned with FindFile(). After that, a normal Dos-operation to
- open the file is issued (so that programs like APPEND may get
- their chance, too).
-
- See also : -
-
-
- Font (*.FNT) files - information
- ────────────────────────────────
-
- There are two types of font files: monochrome and colored fonts. The first
- ones are encoded as an array of bits, while the latter ones are stored as an
- array of bytes, specifying the colors of each point.
- A font file consists of a six byte header:
- - the tag "FNT", showing that this is a font file
- - the width of the chars in pixel (1..MaxFontWidth), that is: 1..15
- - the height of the chars in pixel (1..MaxFontheight), that is: 1..16
- Then follows the data itself; if it is a monochrome font, then each character
- is encoded as a sequence of font height bytes or words, if its width is at most
- 8 pixels or 9..15 pixels, respectively. If it is a colored font, then each
- character is stored as font height times font width bytes.
- The storage order is the same: if you look at an character as a two-dimensio-
- nal array, then each char is stored by storing its pixels row-wise, from top
- to bottom and each row from left to right.
- If the font is proportional spaced, then another 256 byte junk follows, which
- specifies the width of each of the 256 ASCII characters.
- When reading in the data from disk, the font is brought back into a more
- easily two-dimensional standard form for faster access; the necessary memory
- is allocated on the heap: 256*MaxFontHeight*SizeOf(Word)=8K for a monochrome
- font, 256*MaxFontHeight*MaxFontWidth=60K for a colored font.
-
- Note : - There are a lot of monochrome font examples, taken from Michael
- J. Mefford's "FontEdit V1.0" in PC Magazine (Thanks, Joy!)
- Note that most of these fonts aren't fully compatible with
- IBM's "8 bit ASCII"!
- - I added one multi colored font "FIRE.FNT". You have to load and
- activate the palette "FIRE.PAL" prior to the use of this font
- (FYI: it uses colors 0, 26 and 240..255)
-
-
- FontOrient, FontHeight, FontWidth, FontType, FontWidthTable, FontProportion
- ────────────────────────────────────────────────────────────────────────────
- - type/constants
- ─────────────────
-
- Function : Supply some additional data about the actual font
-
- Declaration: TYPE FontOrient=(horizontal,vertical);
- VAR FontHeight,FontWidth,FontType,FontProportion :BYTE;
- FontWidthTable:ARRAY[0..255] OF BYTE;
-
- Description: The fonts used for displaying graphic text (OutTextXY(),
- BackgroundOutTextXY()) can be displayed either horizontally or
- vertically; use of the TYPE FontOrient simplifies that.
- To compute the width/height of a text, the constants FontHeight
- and FontWidth can be used, which specify the size of one letter;
- however, if your font is proportional, then you should use the
- function OutTextLength() to compute a string's width.
- Depending on the font, FontHeightε[1..MaxFontHeight] and
- FontWidthε[1..MaxFontWidth], where MaxFontHeight=16 and
- MaxFontWidth=15 (f-i-f-t-e-e-n).
- FontType specifies, whether the actual font is a monochrome
- font (FontType=TagMonoFont) or if it's a colored font (FontType=
- TagColorFont).
- If FontProportion=TagProportional then the actual font is pro-
- portional spaced. In this case, the width of each character is
- stored in the array FontWidthTable[] and you should use
- OutTextLength() to compute the width of a complete string.
-
- Note : - There is no such thing as "FontHeightTable[]": proportional
- fonts are proportional spaced only in the x-direction
- - For simplicity, FontWidthTable[i] *always* holds the width of
- ASCII-char #i, even if the actual font is _not_ proportional.
- In that case, the table is completely filled with FontWidth.
- - If your font is proportionl, then FontWidth holds the size of
- a char-cell as it is _loaded_ from disk. In most cases this
- is the maximum width an ASCII character may have at all.
-
- See also : OutTextXY, BackgroundOutTextXY, OutTextLength, Font files
-
-
- FreeImageMem - procedure
- ────────────────────────
-
- Function : Releases the memory allocated by a GetImage()-call
-
- Declaration: PROCEDURE FreeImageMem(p:POINTER); FAR;
-
- Description: If you use GetImage(), AniVGA allocates the memory needed and
- returns a pointer to that area, which you can use with PutImage()
- as often as you desire. If you don't need that clipped image any
- longer, you should release its memory so that it can be used by
- other routines again. To do that, just call FreeImageMem() with
- the pointer GetImage() returned to you.
-
- Note : It is this reason -releasing memory- why you shouldn't make an
- "anonymous" GetImage() / PutImage() combination like
- PutImage(x,y,GetImage(x1,y1,x2,y2,1-PAGE),1-PAGE): you don't get
- a handle which could be used to free the occupied memory!
- Of course, you could use "Mark()" and "Release()", but a simple
- additional pointer variable ("p") is better style:
- p:=GetImage(x1,y1,x2,y2,1-PAGE);
- PutImage(x,y,p,1-PAGE);
- FreeImageMem(p)
-
- See also : GetImage, PutImage
-
-
- FreeSpriteMem - procedure
- ─────────────────────────
-
- Function : Releases the memory allocated by a LoadSprite()-call
-
- Declaration: PROCEDURE FreeSpriteMem(number:WORD); FAR;
-
- Description: This procedure is used to "unload" a sprite from memory.
- "number" is the sprite's LOADnumber to wipe out from memory.
-
- Note : - You don't need to call this routine to overwrite a sprite
- (that is: call LoadSprite() a 2nd time with the same sprite
- LOADnumber); AniVGA will do that for you automatically, so
- there is little need to call this routine manually
- - Possible ERROR values returned are Err_InvalidSpriteLoadNumber
-
- See also : LoadSprite
-
-
- GetBackgroundFromPage - procedure
- ─────────────────────────────────
-
- Function : Take over one of the drawing pages as background image
-
- Declaration: PROCEDURE GetBackgroundFromPage(pa:WORD); FAR;
-
- Description: Specify the graphic page (0 or 1) from which the image should be
- "captured" and the routine will copy its contents into the back-
- ground page BACKGNDPAGE (=2) as new background image.
-
- Note : - Use of the routine only makes sense if STATIC is used as
- background mode.
- - Possible ERROR-values returned are Err_InvalidPageNumber
-
- See also : LoadBackgroundPage
-
-
- GetErrorMessage - function
- ──────────────────────────
-
- Function : Returns a description of the last error occured
-
- Declaration: FUNCTION GetErrorMessage:STRING; FAR;
-
- Description: Although you can use the ERROR variable directly to evaluate any
- error and inform the user about it, it is often more comfortable
- to let AniVGA do that: GetErrorMessage will give you a string
- describing the last error which occured in words.
- The possible string contents and the corresponding ERROR values
- are:
-
- Err_None: 'No Error'
- No error occured during the routine; this is the variable's
- initial value
-
- Err_NotEnoughMemory: 'Not enough memory available on heap'
- The program couldn't load sprites or other data to the heap
-
- Err_FileIO: 'I/O-error with file'
- There was an error reading the file; either the file doesn't
- exist at the path given or it is damaged. Another possibility
- is that you compressed your file in a wrong way.
-
- Err_InvalidSpriteNumber: 'Invalid sprite number used'
- This error occurs if you try to load a sprite with a sprite
- loadnumber not in the valid range 1..LoadMAX
-
- Err_NoSprite: 'No (or corrupted) sprite file'
- While attempting to interpret the data just read in, AniVGA
- found the data not to be in the expected format; either because
- you used a wrong data file or it is damaged or compressed wrong.
-
- Err_InvalidPageNumber: 'Invalid page number used'
- There are four graphic pages, numbered 0..3. Page 0 & 1 are
- used for the animation itself, page 2 ("BACKGNDPAGE") holds the
- static background image and page 3 ("SCROLLPAGE") is reserved
- for the scrollable background information
-
- Err_NoVGA: 'No VGA-card found'
- The animation package needs a VGA (or compatible) graphic card
- but couldn't find one
-
- Err_NoPicture: 'No (or corrupted) picture file'
- The background picture file AniVGA should load has not the ex-
- pected size/format or a DOS-error occured while attempting to
- access the data
-
- Err_InvalidPercentage: 'Percentage value must be 0..100'
- If you set the colortable for the shadowing effects of sprite
- display mode Display_SHADOW or Display_SHADOWEXACT, you must use
- a percentage value giving the remaining brightness of the colors
- in the shadow areas, which must be in the range 0..100%, of
- course
-
- Err_NoTile: 'No (or corrupted) tile/sprite file'
- There was an error loading the specified sprite file(s) and
- interpreting them as background tiles. Most often this occurs
- because the sprite doesn't meet the requirement to be a multiple
- of 16 points in its x- and y-directions!
-
- Err_InvalidTileNumber: 'Invalid tile number used'
- There may be only 256 background tiles, numbered 0..255
-
- Err_InvalidCoordinates: 'Invalid coordinates used'
- The virtual background coordinates you use must lie in the range
- (BackX1,BackY1)..(BackX2,BackY2), which has been specified with
- SetBackgroundScrollRange()
-
- Err_BackgroundToBig: 'Background to big for tile-buffer'
- AniVGA's tile buffer can hold no more than MaxTiles (=10000)
- tiles, that is an area of 10000*16*16 pixels². Check the area
- you specified in your SetBackgroundScrollRange()-call!
-
- Err_InvalidMode: 'Only STATIC or SCROLLING allowed here'
- The only background modes AniVGA knows are STATIC and SCROLLING
-
- Err_InvalidSpriteLoadNumber: 'Invalid spriteload number used'
- spriteLOADNumbers must lie in the range 0..LoadMAX; when you
- get this error, you probably confounded a spriteLOADnumber with
- a spritenumber
-
- Err_NoPalette: 'No (or corrupted) palette file'
- You tried to load a palette file which didn't meet the require-
- ments: a palette file must be of size 3..768 bytes and a
- multiple of 3
-
- Err_PaletteWontFit: 'Attempt to write beyond palette end'
- While attempting to read in and store the palette file into the
- actual color table, AniVGA noticed that it would have to write
- beyond the end of that table; decrease your "number" parameter!
-
- Err_InvalidFade: 'Invalid fade style used'
- You tried to use a fade style not supported by the unit: look
- at routine "FadeIn()" for allowed styles.
-
- Err_NoFont: 'No (or corrupted) font file'
- While attempting to interpret the data just read in, AniVGA
- found the data not to be in the expected format; either because
- you used a wrong data file or it is damaged or compressed wrong.
-
- Err_EMSError: 'Problems with EMS memory'
- Some error occured while accessing a EMS routine; you can use
- EMSError to analyze the the error more exactly.
-
- (else): 'Unknown error'
- If ERROR has none of the above values, this string will be
- returned; this should never happen, though.
-
- Note : Calling GetErrorMessage won't set back the ERROR variable either;
- you must do that explicitly!
-
- See also : ERROR
-
-
- GetImage - function
- ───────────────────
-
- Function : Makes a copy of the specified screen region
-
- Declaration: FUNCTION GetImage(x1,y1,x2,y2:INTEGER;pa:WORD):POINTER; FAR;
-
- Description: - This function works much the same as its equivalent in Turbo-
- Pascal: (x1,y1) and (x2,y2) define the upper left and lower right
- corners of the screen part to save, but now these coordinates are
- _virtual coordinates_, the routine reserves the memory needed to
- hold the copy itself and you can specify the graphic page, from
- which the image is to be taken (pa=0, 1, BACKGNDPAGE (=2) or
- SCROLLPAGE (=3) ).
- - As result you get a pointer to the start of the saved image,
- which can be used with PutImage().
- - If there is not enough memory available or the specified part of
- the screen lies completely outside the visible screen, NIL is
- returned.
- - Besides that, there are 5 global variables which are set accor-
- dingly:
- was_cut:BOOLEAN = TRUE/FALSE, if the image had to be _partially_
- clipped (if the specified image is totally offscreen,
- was_cut stays at FALSE!)
- left_cut, right_cut, top_cut, bottom_cut:WORD hold the size how
- much had to be clipped off at the boundaries; these
- values are only set when was_cut=TRUE
- (If you wonder about this odd definitions: GetImage was intended
- to work only with the visible screen (that is: with _absolute_
- coordinates): together with its counterpart PutImage(), you can
- copy a part of the screen to another part or page. In that case,
- you do not have to fiddle around with clipping: just issue a
- GetImage() and use PutImage() to paste this block elsewhere.
- But there may be some applications, when you cut out part of
- the screen and think you got the complete graphic figure you
- wanted, although (because of the use of virtual coordinates and
- your figure being partially offscreen) you got only part of it.
- Checking "was_cut" informs you about such a partial clipping.
- If your figure is completely offscreen, that is a special case:
- it depends on your application whether this should be treated
- as being okay or not; if you need special treatment (as with
- partial clipping), you still can check for this with something
- like:
- ...
- image_ptr:=GetImage(x1,y1,x2,y2,1-PAGE); {1-PAGE=visible page!}
- IF ERROR<>Err_None
- THEN ... {probably not enough memory}
- ELSE IF (was_cut) OR (image_ptr=NIL)
- THEN ... {partial or total clipping occured}
- ELSE ... {no clipping at all}
- )
- - possible ERROR-values returned are: Err_NotEnoughMemory and
- Err_InvalidPageNumber
-
- Note : - As already mentioned, GetImage() only works on screen regions in
- the _absolute_ coordinate range 0..319, 0..199, but expects
- _virtual_ coordinates!
- - To release the memory allocated by a GetImage() call, you must
- use FreeImageMem(); TurboPascal's "Dispose()" won't work.
-
- See also : PutImage, FreeImageMem, coordinates
-
-
- GetModeByte - function
- ──────────────────────
-
- Function : Returns the actual display method set for a sprite
-
- Declaration: FUNCTION GetModeByte(Sp:WORD):BYTE; FAR;
-
- Description: "Sp" specifies the spriteLOADnumber of the sprite from which the
- user wants to know the display mode. The function will return one
- of the valid modes Display_NORMAL, Display_FAST, Display_SHADOW
- or Display_SHADOWEXACT.
-
- Note : - Again, spriteLOADnumbers are used!
- - If the LOADnumber given doesn't exist (because no sprite has
- been loaded with that number), the routine will return
- Display_UNKNOWN instead.
-
- See also : Display modes, SetModeByte
-
-
- GetPalette - procedure
- ──────────────────────
-
- Function : Reads out the actually set color palette directly from the VGA
-
- Declaration: PROCEDURE GetPalette(VAR pal:Palette); FAR;
-
- Description: "pal" specifies the variable in which to store the actual palette.
-
- Note (!) : - This procedure has been added for completeness, merely: As long
- as you make all palette changes by using SetPalette(), you can
- use the variable "ActualColors[]" instead!
- - You must be in graphic mode already or you will get rubbish!
- To state in otherwise: call this routine _after_ having called
- InitGraph() and _before_ calling CloseRoutines()!
-
- See also : SetPalette, Palette, ActualColors
-
-
- GetPixel - function
- ───────────────────
-
- Function : Reads a pixel's color
-
- Declaration: FUNCTION GetPixel(x,y:INTEGER):BYTE; FAR;
-
- Description: Returns the color value of the specified pixel with the virtual
- coordinates (x,y) on graphic page PAGE. If (x,y) lies offscreen
- (to be precise: the computed absolute coordinates lie offscreen),
- then zero (= black) is returned.
-
- Note : Be aware that PAGE is the invisible page, not the one you are
- looking at!
-
- See also : coordinates, PAGE, PageGetPixel, PutPixel
-
-
- GetSplitIndex - function
- ────────────────────────
-
- Function : Determine which sprites will be clipped to the animation window
-
- Declaration: FUNCTION GetSplitIndex:INTEGER; FAR;
-
- Description: If you used SetSplitIndex() to enable that some sprites may be
- drawn outside the animation window, you may use this routine to
- determine which sprites will be clipped and which won't:
- If "n" is the value returned, then this means that...
- SPRITE[0..n] (if active) will not be clipped while
- SPRITE[n+1..NMAX] will
- A return value of "-1" means that all sprites will be clipped;
- this is the default value at start-up.
-
- Notes : -
-
- See also : SetAnimateWindow, WinClip
-
-
- GetTile - function
- ──────────────────
-
- Function : Compute which tile is at a given point
-
- Declaration: FUNCTION GetTile(x,y:INTEGER):BYTE; FAR;
-
- Description: When using SCROLLING background mode, you can use PutTile() to
- link a background tile to a special coordinate. GetTile() is
- the opposite to that: you supply a point (x,y) to it and the
- function returns which tile has been pasted at this corrdinate
- previously.
-
- Notes : If the point (x,y) lies outside of the scroll range which you
- had defined by calling SetBackgroundScrollRange() previously,
- then the routine will return the number of the offscreen tile
- (which you may set by SetOffscreenTile() ).
-
- See also : background, tile, SetBackgroundScrollRange, coordinate, BackX1,
- BackX2, BackY1, BackY2, PutTile
-
-
- GRAB - utility
- ──────────────
-
- GRAB allows you to "steal" graphics from other applications and convert them
- into sprite files (*.COD) or background images (*.PIC) for use with AniVGA.
- This program is a terminate-and-stay-resident (TSR) utility that has to be run
- before starting those applications from which you want to capture graphic
- images.
- It requires a mouse to be installed and a VGA card - note that an EGA won't do!
- Pressing the hotkey CTRL-ALT-G will popup a frame which you can move and resize
- to select the part of the graphic sreen you want to save (if you are not in a
- graphic mode or in a graphic mode unknown to GRAB you'll here a beep instead).
- Note that if you are in a "MSDos critical" situation, GRAB can't pop up.
- Use the mouse to move the box, hold down the left mouse button and drag the
- mouse to resize the box (in "sprite mode" only). The space bar will toggle
- between "sprite mode" and "background mode", pressing the right button will
- store the framed graphic to disk (either as sprite or background image, what-
- ever program mode you are actually in).
- Press ESC (or both mouse buttons simultaneously) anytime to escape from GRAB
- back to your application.
- By default, GRAB starts in sprite capture mode, thus generating sprite files
- (starting with the file name GRAB_000.COD with increasing numbers for the next
- sprites). To get a background image, toggle into screen capture mode by pres-
- sing the space bar (a second press will switch back to sprite capture mode
- again), select the screen region wanted and press the right mouse button to
- get that part of the screen in the file GRAB_000.PIC (or whatever number is
- actual then).
- In both modes, GRAB also dumps the actually set palette to disk, having the
- same number as the COD/PIC file, but with the ending ".PAL" and a (P)icture
- or (S)prite replacing the underscore, e.g. "GRABS000.PAL" for the first
- sprite saved.
- Naturally, you can't resize your frame in the screen capture mode: it stays at
- its initial size of 320x200 points.
- Note that there is the a restriction for a sprite's size: a sprite may be
- 152x152 points in max., if you need bigger sprites then just save the sprite
- as a PIC file and convert it afterwards, using MAKES.
-
- There is only one possible command line parameter when installing GRAB:
- "BIOS": Supplying "BIOS" tells GRAB to use the video bios interrupt INT10h to
- access all video data. This should work on almost every VGA, but is extremely
- slow.
- Otherwise, GRAB defaults to its internal, fast access routines. Note that some
- applications directly reprogram the VGA hardware so that GRAB must fail on
- them (both in default and BIOS mode)!
-
- Note :
- - It may happen that you can't popup GRAB in some applications; if you have
- some commercial screen capture utility, you can use that (most often, they
- are more "radical" in their behaviour, using undocumented Dos-funtions and
- the like).
- Then, use an appropriate viewer program and capture the graphic from their
- display!
- (Sorry, I know there are much situations where GRAB _should_ popup, but
- does not - I'm not content with that, either, but I didn't write the TSR-
- unit, but only use it; _if_ I should find the time, I'll write a more
- suitable TSR-unit on my own)
- - Especially if you save a screen as a PIC file, it will take quite a long
- time until GRAB finishes its operation - be patient!
-
- See also : MAKES, Palette
-
-
- GraphTextBackground, GraphTextColor, GraphTextOrientation - variables
- ─────────────────────────────────────────────────────────────────────
-
- Function : Determine how the OutTextXY()-procedures work
-
- Declaration: TYPE FontOrient=(horizontal,vertical);
- CONST GraphTextOrientation:FontOrient=horizontal;
- GraphTextColor:BYTE=white;
- GraphTextBackground:BYTE=white;
-
- Description: Whenever text is to be written to the graphic screen, AniVGA
- consults some global variables. GraphTextColor is simply the color
- in which the text should be drawn, GraphTextBackground specifies
- the color for the pixels in between the letters with one special
- value: if GraphTextBackground=GraphTextcolor, then only the pixels
- belonging to the letters will be drawn with all others remaining
- unchanged.
- Of course, if you are using a colored font, then the font itself
- determines its colors. The only exception of that rule is color
- 0, which is treated as in the monochrome case: if
- GraphTextBackground=GraphTextcolor, then only the pixels
- belonging to the letters will be drawn with all others remaining
- unchanged.
- Finally, GraphTextOrientation tells AniVGA in which direction the
- text should be written with two values being possible: HORIZONTAL
- (default) for left-to-right text and VERTICAL for top-to-bottom
- style text.
-
- Note : Default (monochrome) color for the text is "white/white" =
- "white and don't change pixel values between letters".
-
- See also : OutTextXY, BackgroundOutTextXY
-
-
- HitDetect - function
- ────────────────────
-
- Function : Checks whether two sprites collide or not
-
- Declaration: FUNCTION Hitdetect(s1,s2:INTEGER):BOOLEAN; FAR;
-
- Description: Call this routine with the sprite numbers of the two sprites to be
- checked for collision; the function will return TRUE/FALSE when
- the sprites collide/do not collide, respectively.
-
- Note (!) : - Collision detection is independent of whether the sprites are
- visible or offscreen: AniVGA uses the corrdinates of the two
- sprites given (in SpriteX/Y) and internal data to check.
- - For this it is possible to check for collisions _before_ drawing
- an image (with Animate) and thus make necessary sprite updates
- at once!
- - Inactive sprites cannot collide:
- (SpriteN[s1] or SpriteN[s2]=0) -> FALSE
- - A sprite can't collide with itself: (s1=s2 -> FALSE)
-
- See also : Collision-detection
-
-
- InitGraph - procedure
- ─────────────────────
-
- Function : Initialises the VGA card for the use with AniVGA
-
- Declaration: PROCEDURE InitGraph; FAR;
-
- Description: AniVGA uses a special graphic mode, which supports 4 graphic pages
- in the resoultion 320x200 pixels and 256 colors. Because this mode
- is not known by the VGA's BIOS, AniVGA has to reprogram the VGA.
- You should use this command only once to switch into graphic mode.
-
- Note : InitGraph automatically switches to the invisible graphic page
- 1-PAGE.
-
- See also : Screen, CloseRoutines
-
-
- InitRoutines - procedure
- ────────────────────────
-
- Function : Resets all necessary internal variables of AniVGA to initial values
-
- Declaration: PROCEDURE InitRoutines FAR;
-
- Description: At program start, some variables have to be set and a few system
- checks are necessary.
- Among these are:
- - SpriteN[], SpriteAd[], SpriteSize[], SpritePTR[] and BackTile[]
- become cleared (=set to 0 or NIL, respectively)
- - Page (the actual drwaing page) is set to 0
- - PageAdr is set to the segment address of the drawing page PAGE
- - BackgroundMode is set to STATIC, i.e.: non-scrollable background
- - BackGndAdr is set to the segment address of the background image
- - StartVirtualX/Y are set to (0,0), making the normal screen coor-
- dinates identical to the virtual screen coordinates
- - the old graphic/text mode which was active at program start is
- stored for restoring it at the program end
- - the system is checked if a VGA card is present and the global
- variable ERROR is set accordingly
- - CycleTime is set to 0, which says that there should be no time-
- control mechanism for the animation rate
- - if the machine is not at least an AT, the time mechanism is
- switched off completely
- - COLOR is set to 15 (= white)
- - the internal monochrome 6x6 font is activated
- - the FONT* variables are set accordingly
-
- The first thing you should do in your programs is to look at the
- ERROR variable: if it was set to something different from Err_None
- (by the implicit, automatical call of InitRoutines) then your pro-
- gram should not proceed further.
-
- Note : - This routine is called automatically at the very beginning of
- every program which uses AniVGA. For that, there is normally no
- need to call this routine explicitly.
- - Possible ERROR-values returned are: Err_None and Err_NoVGA
- - Note that this is the _only_ routine that definitely sets the
- variable ERROR, either to Err_None or Err_NoVGA. Because it is
- called at the beginning of every program, it is thus assured
- that your application always has a defined value for ERROR!
-
- See also : ERROR
-
-
- IntroScroll - procedure
- ────────────────────────
-
- Function : Does a hardware scroll on the video RAM
-
- Declaration: PROCEDURE IntroScroll(n,wait:WORD) FAR;
-
- Description: A feature often asked is a big, smooth scrolling intro screen.
- This can be done with IntroScroll(): you load up to 4 graphic
- pics into the 4 graphic pages 0..3 and then issue IntroScroll.
- The scroll will *always* start at graphic page 0 and last "n"
- rows. After each row being scrolled, the system will pause for
- "wait" milliseconds before the next line will be scrolled.
- This routine is only for an intro, you can't use sprites in
- parallel and must issue a "Screen(1-page)" command afterwards!!!
- A small example:
-
- USES AniVGA;
- BEGIN
- InitGraph; {program VGA card into graphic mode}
-
- {--- Start Of Intro ---}
- Screen(0); {show page 0; not necessary, but nicer :-) }
-
- {Fill all 4 pages with data; of course you could also }
- {restrict yourself to pages 0..2 or 0..1:}
- LoadPage('3rd.PIC',1); {load temporarily to page 1}
- {move picture to VRAM area of former background page:}
- CopyVRAMtoVRAM(Ptr($A000,1*PAGESIZE),
- Ptr($A000,2*PAGESIZE),
- PAGESIZE);
- LoadPage('1st.PIC',0);
- LoadPage('2nd.PIC',1);
- LoadPage('4rd.PIC',3);
-
- IntroScroll(3*200,20); {scroll up 3 pages, wait 20ms}
- {as scrolling starts at page 0, you will end up at page 3}
-
- READLN; {wait for a CR by the user}
- Screen(1-page); {restore correct mode, this is a must!!!}
- {--- End Of Intro ---}
-
- {now do your animations as usual: sprites, backgrounds, etc.}
- {...}
- CloseRoutines;
- END.
-
- Note the special treatment of the picture "3rd.pic": a simple
- "LoadPage('3rd.PIC',2)" wouldn't work, as it would load the
- picture into the background page --but this has been moved to
- normal RAM (or EMS) in V1.2. However, for a hardware scroll, the
- data *must* be in consecutive order in the VRAM area! So we load
- the pic into some other VRAM page and move it to the right place.
- (If you don't understand: don't mind, just behave as in the
- example above!)
-
- Note : - This routine is thought for *intros*! Remember that graphic
- pages 2 and 3 (=BACKGNDPAGE and SCROLLPAGE) are used by AniVGA
- for other purposes, so if you use them for your intro, don't
- forget to fill them later with the proper contents for your
- animations! (In version V1.2, BACKGNDPAGE has been moved to
- RAM, so its former VRAM address range has been freed).
- - You have to issue a "Screen(1-page)" command at the end of your
- intro to reset the VGA card properly!
- - It's merely for this routine that AniVGA's routines allow you
- to treat pages 2 and 3 as "normal" graphic pages.
- - This routine is "the hacker's toolkit". You are discouraged
- to use it; maybe it won't be supported in future versions or
- its interface will change.
-
- See also : CopyVRAMtoVRAM, FadeIn
-
-
- Library files - information
- ───────────────────────────
-
- The term "library" is used in two meanings throughout the manual:
- - in specifying a sprite library file (*.LIB)
- - in specifying a collection of data sets (of any kind, although that's more
- theoretical for our considerations here) in a compressed file
- I'll reference you to "Sprite library" for the first point and to "BFFFFFFF"
- for the second one; this paragraph is just to remind you, that there are these
- two different meanings.
- However, you shouldn't get the chance to get confused: a sprite library is
- just a collection of data sets (namely: sprites), too. So these two terms can
- be seen as identical for your purposes, as long as you remember what is said
- at the "BFFFFFFF" description: never compress a (sprite) library, which has
- already one or more compressed sprites in it.
- If you live up to that rule (or doesn't use compression of *.LIB files at
- all), then just forget about this section!
-
-
- Line - procedure
- ────────────────
-
- Function : Draw a line between the two points specified
-
- Declaration: PROCEDURE Line(x1,y1,x2,y2:INTEGER; pa:WORD); FAR;
-
- Description: Calling this routine will draw a line between the two points
- (x1,y1) and (x2,y2) on graphic page "pa" and in the color COLOR.
- The routine uses virtual coordinates and clips the line down to
- its visible part.
- "pa" must be one of the values 0, 1, BACKGNDPAGE (=2) or
- SCROLLPAGE (=3).
-
- Note : - As with all point-setting procedures of AniVGA, you have to re-
- member AniVGA's working scheme: the first thing AniVGA does when
- Animate becomes executed is to copy the background image to the
- actual drawing page PAGE, erasing everything on that image.
- For this reason, a line drawn on the visible page 1-PAGE will be
- visible exactly one animation cycle.
- - Possible ERROR-values returned are: Err_InvalidPageNumber
-
- See also : PutPixel, BackGroundLine, coordinates
-
-
- LoadBackgroundPage - procedure
- ──────────────────────────────
-
- Function : Loads a background image from disk
-
- Declaration: PROCEDURE LoadBackgroundpage(name:String); FAR;
-
- Description: This routine loads a bitmap image stored in file "name" into the
- graphic page used for the background image (BACKGNDPAGE).
-
- Note (!) : - This routine must be called *after* the graphic mode has been
- initialized (with InitGraph())!
- - You can create such images either with the WritePage()- and
- WriteBackgroundPage()-routines of AniVGA or the GRAB-Utility.
- - Calling this routine is equivalent to use the routine LoadPage()
- with BACKGNDPAGE as second argument.
- - Possible ERROR-values returned are: Err_FileIO and Err_NoPicture
-
- See also : Background, LoadPage, FillBackground, GetBackgroundFromPage,
- InitGraph, FindFile
-
-
- LoadFont - procedure
- ────────────────────
-
- Function : Loads a font file from disk
-
- Declaration: PROCEDURE LoadFont(name:String); FAR;
-
- Description: With this function, you load a font from disk into memory and
- make it the actual font. "name" is the MSDos-name of the font
- (*.FNT) file or the empty string '' to reset the font used to
- the internal monochrome 6x6 font.
-
- Note : - Only one font may be in use at one time; loading a new one
- cancels the old one
- - The variables FontHeight, FontWidth, FontType, FontProportion,
- FontWidthTable[] and CurrentFont, which are linked to a font,
- are adjusted automatically
- - Possible ERROR-values are: Err_FileIO, Err_NotEnoughMemory and
- Err_NoFont
-
- See also : FontHeight, FontWidth, FontType, Font files, FindFile
-
-
- LoadMAX - constant
- ──────────────────
-
- Function : Specifies the maximum number of different sprites
-
- Declaration: CONST LoadMAX=1000;
-
- Description: For each physical sprite, AniVGA uses an internal pointer to its
- data. There are LoadMAX pointers, thus there may be up to LoadMAX
- different spriteLOADnumbers (= different sprites).
-
- Note : Don't mix this constant up with NMAX!
-
- See also : NMAX, SPRITE, SpriteLOADnumbers, Spritenumbers
-
-
- LoadPage - procedure
- ────────────────────
-
- Function : Loads a graphic page from disk
-
- Declaration: PROCEDURE LoadPage(name:STRING; pa:WORD); FAR;
-
- Description: "name" is the MSDOS-path to the graphic image to load, pa the
- destination page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE (=3)).
-
- Note : - The graphic mode must have been initialized (vià InitGraph)
- already!
- - You can generate disk files of graphic pages with the help of
- the WritePage()-routine or with the GRAB-utility program.
- - Don't use this routine to load an image into the SCROLLPAGE,
- i.e.: in background mode SCROLLING!
- - Possible ERROR-values returned are: Err_InvalidPageNumber,
- Err_FileIO and Err_NoPicture
-
- See also : GRAB, WritePage, background, InitGraph, FindFile
-
-
- LoadPalette - function
- ──────────────────────
-
- Function : Loads a palette into memory
-
- Declaration: FUNCTION LoadPalette(name:String; number:BYTE;
- VAR pal:Palette):WORD;
- Description: "name" is the MSDOS-name of the palette file (*.PAL) to load,
- "number" is the index of the first loaded color in the desti-
- nation array "pal". For example,
- LoadPalette('C:\AniVGA\TEST.PAL',0,my_pal)
- would load the named palette file into my_pal and the first color
- of this file would be stored in my_pal[0], the second in
- my_pal[1] and so on. (This call - "number" set to 0 - will be
- the form you'll need in 99% of all cases!)
- The routine will read in the complete file and return the number
- of colors read as result.
- All other colors in "pal" before "number" or after the end of the
- specified pal-file will stay untouched!
-
- Note : - As the routine reads in the complete file, you must take care
- not to write beyond the end of "pal"! Especially, if you load
- a complete 256-color palette (size: 3*256=768 bytes), you must
- start at color index 0 (that is: number=0) or you'll get an
- "Err_PaletteWontFit"-Error! Most often however, you will use
- this routine as in the example above.
- - Other possible errors are: Err_FileIO and Err_NoPalette
- - You can call this routine only after having called InitGraph()!
- - You can directly load into ActualColors, that is the sequence:
- Dummy:=LoadPalette(pal_name,0,ActualColors);
- SetPalette(ActualColors);
- is valid!
-
- See also : palettes, SetPalette, GetPalette, FindFile
-
-
- LoadSprite - function
- ─────────────────────
-
- Function : Loads one (or more) sprites into memory
-
- Declaration: FUNCTION LoadSprite(name:String; number:WORD):WORD; FAR;
-
- Description: "name" is the MSDOS-name of the sprite file to load, which can be
- either a single sprite file (*.COD) or a complete sprite library
- (*.LIB): the function will detect automatically, which format is
- used while loading the data.
- "number" is the spriteLOADnumber, the first loaded sprite will be
- assigned to. If the file contains more than one sprite, they will
- get consecutive LOADnumbers.
- The value returned by the function is the numbers of sprites read
- in (i.e.: 0 means "no sprite read", so you should check ERROR in
- that case).
-
- Note : - Unlike LoadTile(), LoadSprite() loads data into conventional
- memory. For that, you don't have to be in graphic mode to load
- data from disk!
- - If you load a sprite at a LOADnumber already used, the old
- sprite will become erased automatically by a call to
- FreeSpriteMem()
- - Possible ERROR-values returned are: Err_FileIO, Err_NoSprite,
- Err_NotEnoughMemory and Err_InvalidSpriteNumber
-
- See also : FreeSpriteMem, sprite format, MAKES, FindFile
-
-
- LoadTile - function
- ───────────────────
-
- Function : Loads one or more tiles from disk
-
- Declaration: FUNCTION LoadTile(name:STRING; number:BYTE):WORD; FAR;
-
- Description: This routine loads the background tile file "name" into the
- graphic memory area reserved for tiles (the SCROLLPAGE).
- The starting number for the first tile of the file is "number";
- if there is more than one tile in the named file, they will be
- loaded, too (with increasing numbers).
- The function returns the number of tiles read in.
-
- Note (!) : - This routine must be called *after* the graphic mode has been
- initialized (with InitGraph)!
- What the function actually does is reading in a sprite and con-
- verting it into an internal tile format: if the sprite read in
- doesn't have the proper size of a tile (16x16 pixels), you nor-
- mally will get an appropriate error (Err_NoTile), with one (use-
- ful) exception: if the sprite can be "cut" into tiles (that is,
- its width and height are multiples of 16 pixels each), then
- LoadTile() will do so with the following numbering scheme: from
- left to right and from top to bottom.
- For example, a sprite with (width,height)=(3*16,2*16) points
- would be numbered as: (assuming that "number" = 0)
- ┌────────┬────────┬────────┐
- │ │ │ │
- │ 0 │ 1 │ 2 │
- │ │ │ │
- ├────────┼────────┼────────┤
- │ │ │ │
- │ 3 │ 4 │ 5 │
- │ │ │ │
- └────────┴────────┴────────┘
- Besides, LOADTILE can load a sprite library, too (they will be
- loaded in the sequence in which they appear in the library).
- - Possible ERROR-values returned are: Err_NotEnoughMemory,
- Err_FileIO, Err_NoTile and Err_InvalidTileNumber
-
- See also : Background, LOADSPRITE, TILE, FindFile
-
-
- MAKES - utility
- ───────────────
-
- The design of sprites, background pictures and tiles is much to tedious to be
- carried out manually. For this reason, there are two utility programs to
- simplify that task. The first one is a resident program named "GRAB" to
- capture graphics from other applications and convert them into sprites, the
- second is MAKES, a spritemaker program.
- To use it, you must have a mouse installed and a Super-VGA card.
-
- -> MAKES uses a "tweaked" 640x400x256 graphic mode, only available at Super-
- VGA-cards! If you don't have one (or one which chip-set isn't supported by
- the supplied BGI-driver), you won't be able to run MAKES!
- Let me cite from Jordan Hargrave's docs:
-
- >Card types supported: (SuperVGA drivers)
- >Ahead, ATI, Chips & Tech, Everex, Genoa, Paradise, Oak, Trident (both 8800
- >and 8900), Tseng (both 3000 and 4000 chipsets) and Video7.
- >These drivers will also work on video cards with VESA capability.
- >
- >I have not tested these drivers on all these card types, so I can not
- >guarantee perfect operation with your card. I have tested them extensively
- >on Trident, Tseng and ATI cards, and have had no problems. (Trident 8800
- >cards occasionally have problems, especially older models)
-
- If you can't run MAKES, then please drop me a note specifying which brand of
- VGA card you have and which chip-set it uses!
-
- There are normally no parameters or such things, just start it!
- (However, if you _do_ have a SVGA and MAKES does not show its graphic screen
- properly, then use the syntax "MAKES /480" to invoke the program in
- 640x480x256 graphic mode instead)
-
- The screen is divided in several areas:
- - the so-called "work area" in the upper left region, in which you paint your
- sprite
- - the palette area to the right of it, where you choose colors for painting
- or define new colors
- - the info bar right beneath the work area, which informs you about the
- cursor position and some other actually set data
- - the icon field, supplying 18 different functions: 8 "tools" and 10 pure
- functions
- - 10 function boxes at the very screen bottom, which can also be accessed by
- pressing the appropriate function key (ever seen the Norton Commander?)
-
- (Note that a lot of the icons/function boxes have two functions, where the
- second one can be reached by holding down the shift-key while pressing/
- clicking at the icon - this will be described later on, but you can always
- press F1 in MAKES for a short summary.)
-
-
- Now let's take a small tout through MAKES!
-
- -> I propose that you print out this part of the documentation and then start
- MAKES.EXE for the following description!!!
-
- Huh - where to begin? Okay, look at the work area's boundary: it has small
- marks on it, indicating 8 pixel intervals. Move the mouse cursor somewhere into
- the workarea: right beneath the work area, your PC will display the mouse
- cursor's position and what color is currently set at that point. Now move around
- and convince yourself about the marks' values. Press the left mouse button a
- few times: each time, a white pixel will be drawn at the cursor position,
- because "pixel" is the selected tool and "white" the actually set drawing color.
- Nothing whopping, eh? - Now press "+" a few times: wow! You zoom into the work
- area as much as you wish (well, I limited it to a factor 30, but if _that_ is
- not enough you should consider selling your PC for a seeing-eye dog, anyway!).
- Use "-" to zoom out, down to value 1: for easier pointing, the cursor will
- change to a small crosshair pointer when zooming is at factor 1.
- -> Note that as the screen you look at has resolution 640x400, while AniVGA's
- has 320x200, zoom=2 (the default value) will give you normal 1:1 aspect
- ratio!
- You don't like monochrome pictures? Ok, then click (with the left mouse button)
- at another color in the palette area: this changes the drawing color to the
- color you clicked at.
- Repeat choosing a color, but this time press the _right_ mouse button: a menu
- will pop up and let you change the RGB-values of that color; this way, you may
- alter the palette for your sprites!
- -> Note that RGB-values reach from 0 to 63. If you want to copy another color's
- values, then just click at this color; e.g. if you want to have color 222
- hold the same color as 111 (for example as a template), then click with the
- _right_ button at color 222 and then with the _left_ button at color 111
- Now choose another drawing tool, let's say lines: click at this icon and move
- back into the work area. Choose a starting point and click at it (release the
- mouse button!): now you started a line: move around the mouse to route your
- line; if you are content with it, then press the left button again. If you
- decide to cancel the line drawing instead, then press the right button instead.
- -> This "philosophy" will be used for all tools: press the left button to
- start/advance/complete an action, press the right button any time to cancel
- what you are doing - so get used to it!
- Now repeat the process of drawing a line, but hold down "shift" while you are
- clicking at the starting point: this tells the object "to be aligned" which
- in the context of lines means that you are drawing a horizontal, vertical or
- diagonal line! In the same way, you can align rectangles to become squares and
- ellipses to circles. Try it! Choose these icons and draw the according objects,
- aligned and not aligned (if you choose the lower rectangle/ellipse icon, your
- objects will be filled out with the actual drawing color).
- -> You may select another color even if you are in midst of drawing an object;
- move out of the work area, click at the color you wish - as soon as you
- move back into the work area, your object will change!
- Let's try the filling tool (the left, bottommost one): it will fill all points
- it can reach from the pixel you clicked at having the same color, e.g. if you
- click at a white pixel, it will color all white pixels neighboured to that
- pixel and so on. Note that as long as you don't press the left button a second
- time, this coloring doesn't rest, that is if you move around the mouse after
- having clicked the first time, MAKES will restart its fill algorithm starting
- at the new pixel your mouse points at! This behaviour is a bit confusing in
- the beginning but comes in very handy when you get used to it.
- -> If you really get stuck - especially on slow machines - then just press the
- right mouse button for two or three seconds to cancel the action and start
- over again.
- The last tool to be mentioned is the copy tool (the icon with the scissors):
- you can span a (dotted) rectangular area which you want to copy the same way
- you would draw a rectangle, but after pressing the mouse button a second time,
- a copy of this area will be visible at your cursor which you can place where-
- ever you want to. (Note that color 0 inside this copy will be treated as trans-
- parent, which makes it easier to overlay objects at the screen!)
-
- These 8 icons (the 4 leftmost in the upper and lower row) make up the available
- _tools_, the resting 10 icons are "function buttons", that is: their linked
- action will take place at once (respectively: after asking you necessary para-
- meters).
- I'll first name them, starting in the upper row at the 5th icon, in clockwise
- order:
- a) change color
- b) rotate work area left
- c) rotate work area right
- d) mirror work area horizontally
- e) go/move to the upper-left
- f) display boundaries
- g) mirror work area vertically
- h) rotate work area down
- i) rotate work area up
- j) blink color
-
- a)
- You can replace pixels of a specific color by another color with this tool:
- the program will ask you for the colors, which you can select by either
- clicking in the palette area or by clicking at pixels in the work area itself.
-
- b), c), h), i)
- Clicking at one of these buttons will move the contents of the work area in
- the according direction, but what "falls out" at one side of the work area
- will show up on the opposite side again. If you hold down "shift" while
- clicking, the image will rotate by one pixel, without shift, it will rotate
- by 1/4 of the actual screen width.
-
- d), g)
- I guess these two mirror options should be quite clear; note that as
- they mirror a small image in the upper left corner to the "far away" right/
- bottom region of the work area, you'll often need a tool to "pull back" the
- graphic contents to the upper left corner: that is exactly the task of the
- e) icon: it will move the graphic contents to the top and left as much as
- possible.
-
- e)
- As mentioned above, this tool will move the work area contents to the left
- (and top), until column 0 (row 0) holds a non-zero colored pixel.
- If you hold down "shift" while clicking at this icon, there is another
- functionality: then, MAKES scrolls back the visible part of the workarea
- back to the upper left region of the picture (0,0), that is: this is a short-
- cut for pressing the left- and up-arrow keys a few times (see below for more
- about this).
-
- f)
- If you want to know/see the boundaries of your sprite, then click at this
- icon: the leftmost and rightmost (upmost & bottommost) pixel of each row
- (column) will blink and a popup window will inform you about the sprite's
- size numerically.
- If you hold down "shift" while clicking this icon, MAKES will also blink all
- transparent areas inside the sprite, which may be useful if you don't know
- whether you must use display mode Display_SHADOW <-> Display_SHADOWEXACT and
- Display_FAST <-> Display_NORMAL; in all other cases you can forget about this
- option.
- -> Note that sprites are always stored as the smallest rectangle which
- surrounds them and starts at the upper left corner (0,0): if you don't have
- special reasons to do otherwise, your sprites should start in the upper left
- corner.
- If for example you realize a sprite consisting of one single point at
- coordinates (a,b), the smallest surrounding box with (0,0) as upper left
- corner would be
- (0,0) (a,0) of size (a+1)*(b+1) pixels (=bytes)!!!
- ┌──────────┐
- │ │
- │ │
- │ │
- └──────────▀ <─ this is your 1 point
- (0,b) (a,b)
- (In addition to that, the right edge of this box will be rounded up so that
- the width of the sprite will be a multiple of 4)
- To determine what areas belong to your sprite and which don't, the program
- assumes color 0 to specify no-sprite-areas and all other colors to be part
- of your sprite (roughly spoken).
-
- j)
- If for some reason you must know of all pixels of a specific color (e.g. to
- distinguish two very similiar colors), you can use this function: the program
- will ask you to select the color, what you can do by either clicking at a
- work area pixel with that color or at a color in the palette area.
-
- Okay, now that we are through with the icons, let's have a look at the keys:
- you already know that "+" and "-" zoom in and out the workarea. But if zoom>1
- then only a part of the complete workarea (320x200 pixels) will be visible!
- To work on the "offscreen" regions, you can scroll the work area by using the
- cursor keys: pressing one of the arrow keys will scroll by 1/4 screen into the
- corresponding direction; if you hold down "shift" while pressing an arrow key,
- it will scroll by one pixel instead. The absolute coordinate value of the
- upper left corner you are looking at will be displayed by the two "offset:"
- messages, e.g. "offset X: 40" means that there are 40 columns (0..39) to the
- left of the visible window of the work area, which you may scroll in by
- pressing the left arrow key. (Consider the work area as a view-finder of an
- imaginary camera which you may slide into each direction).
- A short-cut to return to the work area's origin (0,0) is available, too: press
- shift and click at the "go/move to upper left" icon.
-
- The function keys do what they tell you:
- F1 = a short summary of the functionality not visible at first sight
- F2 = save the work area's contents to disk as a sprite file
- F3 = load a previously saved sprite into the work area; if you press "shift"
- while activating this icon (or Shift-F3), then the work area won't be
- erased before loading the sprite: this way, you may overlay several
- sprites on the screen
- F4 = save the actually set palette to disk. Note that if you are using the
- BIOS' default palette, the program won't store it to disk (as you don't
- need)
- F5 = load a previously saved palette. This function is especially necessary
- when you used GRAB to capture a sprite from an application using a
- different palette. (See below for more about palette handling)
- F6 = save the work area's contents to disk, this time as a background picture
- F7 = load a previously saved background picture; the same notes apply as said
- to loading sprites (F3)
- F8 = clear screen. This will erase the work area and let you start all over
- again. Note that it won't reset the palette to the BIOS' default! If you
- want that, you have to press Shift-F9, too!
- F9 = map the workarea colors onto another palette. This feature asks you for
- a palette, loads that and then uses a minimum square algorithm to exchange
- each's pixel color by the one from the specified palette which comes as
- close as possible to the original color. (See below for more about that)
- Shift-F9 works the same, but maps to the BIOS' default palette instead
- of asking you for a palette file.
- F10= quit the program
-
-
- Note :
- o Palettes:
- Note that if you load/save a sprite or picture file, MAKES won't load/save
- the according palette automatically, you have to do that manually. This has
- been done intentionally, however: never forget that you may design a hundred
- sprites with a hundred different palettes, but when it all comes down to
- display these sprites simultaneously in your programs, only *one* palette may
- be active! For that reason, you must mix all those palettes to the one you are
- going to use.
- Normally, that won't be that dramatic, as 240 free color shades (it is *very*
- wise not to change the first 16 EGA-compatible colors) seem enough to me, but
- perhaps you want to include a formerly designed sprite A, using palette B,
- into a new program where you use palette C! Before you start mixing a new
- palette D for this old and your new sprites together, you should try mapping
- old sprite A's colors to palette C: To accomplish that, load sprite A (using
- F3), then load its old palette B (using F5); now press "map palette to
- palette" (F9) and tell the program to map onto palette C: if the result looks
- good enough, then save sprite A (perhaps using a different name) and use
- palette C for all items in your program, else you have to find a compromise
- between palettes B and C (I'm actually working on a program which will auto-
- matize that job, but for now, you are on your own!).
-
- To state it clear: there is a conceptional difference between EXCHANGING a
- color (using the "change color" icon) and CHANGING a color itself (by altering
- the RGB values of one or multiple colors):
- - exchanging colors doesn't change the palette, it merely uses another color
- of that palette
- - changing palette colors doesn't change the pixels' color number, but the
- color's RGB value
- In other words: if you exchange colors, then you don't have to save the color
- palette again, as it didn't change, but the sprite, because its data changed.
- On the other hand, if you changed palette colors, then you'll have to save the
- palette, but not the sprite, as the pixel data didn't change.
- (If you didn't get that: just always save both and forget about it...)
-
- o Mouse problems:
- I noticed that sometimes, the program hangs when initializing the mouse driver
- (when it calls "INT 33h" with AX=0), what you see in that the starting count-
- down doesn't get below 7. I don't have _any_ idea why this happens and hope
- it won't show up on other systems. Note that this is (at least what I noticed)
- a spurious error: cancel the program, restart it once more and it will work!
- Besides that, when quitting the program, MAKES sometimes reports a senseless
- runtime error - it is a spurious, not reproducable error I couldn't track
- down, either (perhaps TP doesn't like my TSR / QEMM installation, I dunno)!?
-
- o SVGA-compatibility problems:
- The 640x400x256 mode seems to make problems on some SVGAs, especially ones
- with Paradise chipsets. Therefore, a command line switch "/480" has been
- added. If you use this switch, the program will start in 640x480x256 mode
- instead. I've been reported that this mode works on almost all cards; the
- only disadvantage is, that the aspect ratio differs from the 320:200 (resp.
- 640:400) mode. (Tip: use your monitor's vertical adjustment controller to
- spread the image accordingly if this is a problem for you)
-
- o Memory:
- You should have at least 256K free RAM if you start MAKES, or it won't work.
-
- o Sprite size:
- If MAKES tells you that it can't save the workarea as a sprite, because it
- is "to big" - well, then you'll have to shrink your sprite! Sorry, but I
- wanted MAKES to handle CODs and PICs at the same time, but 320x200 pixels
- (the size of a picture) is to much for a COD, as the additional data stored
- along with the sprite would make it larger than 64K! (Cut off a few rows or
- columns until it works.)
- Note also that MAKES has to store sprites with widths being a multiple of 4!
- That is: it doesn't matter, whether the max. used x-coordinate is for example
- 316, 317, 318 or 319, because for all those 4 widths (0..316=317 pixels,
- 0..317=318, 0..318=319, 0..319=320), MAKES would have to store them with
- the "rounded up" width of 320 pixels!
- (In other words: although AniVGA itself can handle sprites up to 32000 pixels
- in each axis and 64K max. size, MAKES restricts you to sprites of x-size at
- most 320 pixels and y-sizes of at most 200 pixels)
-
- o COD <-> PIC:
- Yes, you read right: MAKES doesn't care whether you are working on a sprite
- or a picture graphic: just paint it and store it into the format you want
- (subject to what I said above concerning the 64K limit)! Oh yes, that way
- you may convert a sprite into a background picture (and vice versa) if you
- have reason to do so!
-
- o Tips:
-
- The best way to design a sprite is to start in midst of a cleared work area.
- If you need more room, rotate your sprite in the appropriate direction.
- If you think you're done, use the rotate boxes again (or the "move to upper-
- left" icon) to align your sprite with the upper left corner. Then click on
- the "display boundaries" box to compare the sprite's size with what you
- expected. To wide (high)? Then there is a pixel with color <> 0 to the right
- (beneath) your sprite! Look at the max. column (row) MAKES told you and kill
- that pixel! (To see it more clearly, just hold down "shift" while clicking
- at the "display boundaries" icon).
-
- If you are unsure whether you can use display mode Display_FAST or need
- Display_NORMAL (same applies for Display_SHADOWEXACT and Display_SHADOW),
- then hold down "shift", click at the "display boundaries" icon and look at
- the picture: if the blinking parts "spread" out of the parts you think your
- sprite should be made of, then you should use Display_NORMAL
- (Display_SHADOWEXACT, respectively), if all the blinking areas are inside your
- sprite, you can (and should) use Display_FAST (Display_SHADOW).
-
- See also : sprite format, GRAB, Display modes
-
-
- MakeTileArea - procedure
- ────────────────────────
-
- Function : Simplifies tiling of the background area
-
- Declaration: PROCEDURE MakeTileArea(FirstTile:BYTE;
- TileWidth,TileHeight:INTEGER); FAR;
-
- Description: When using background mode SCROLLING, you have to define which
- tile should be "pasted" where in the coordinate space.
- You can do so manually for complete control, but most often,
- you just want to repeat a rectangular pattern throughout the
- complete scroll range which you did define before.
- This is exactly what MakeTileArea() does for you: you tell it
- in "FirstTile" the index of the first tile to use and the width
- and height of your pattern in tiles in "TileWidth" and
- "TileHeight" and it will paint this pattern throughout the
- defined background scroll range.
- For example, let's assume that you have a pattern 3 tiles wide
- and two 2 tiles high. The starting tile has index 7:
- ┌──┬──┬──┐
- │ 7│ 8│ 9│
- ├──┼──┼──┤
- │10│11│12│
- └──┴──┴──┘
- To set up the background area to a repetive pattern structure
- like that...
- ┌──┬──┬──┬──┬──┬──┬──┬
- │ 7│ 8│ 9│ 7│ 8│ 9│ 7│...
- ├──┼──┼──┼──┼──┼──┼──┼
- │10│11│12│10│11│12│10│...
- ├──┼──┼──┼──┼──┼──┼──┼
- │ 7│ 8│ 9│ 7│ 8│ 9│ 7│...
- ├──┼──┼──┼──┼──┼──┼──┼
- │10│11│12│10│11│12│10│...
- ├──┼──┼──┼──┼──┼──┼──┼
- . . . . . . .
- . . . . . . .
-
- ...all you have to do is a call MakeTileArea(7,3,2)!
-
- Note (!) : - Of course, usage of this routine requires that you are using
- background mode SCROLLING _and_ that you had issued a call to
- SetScrollRange() before!
-
- See also : Background, SetScrollRange
-
-
- MaxTiles - constant
- ───────────────────
-
- Function : Holds the maximum number of tiles to build the background image
-
- Declaration: CONST MaxTiles=10000;
-
- Description: In background mode SCROLLING, you may use up to MaxTiles tiles
- to build your graphic image.
-
- Note : -
-
- See also : Background
-
-
- NextSprite - variables
- ──────────────────────
-
- Function : Holds the "successors" of sprites for sprite cycles
-
- Declaration: VAR NextSprite: ARRAY [0..LoadMAX] OF WORD
-
- Description: To realize a sprite cycle, you must tell AniVGA which sprites
- should be drawn one after another. It is this information
- NextSprite holds! For example, let us assume that you wanted to
- make the sprite(loadnumber)s 43, 177 and 111 a sprite cycle, i.e.:
- whenever you set a sprite (to be precise: a SpriteN[]-entry) to
- one of these three numbers, AniVGA should cycle between the three
- sprite-images in the sequence 43->177->111->43->177->111->...
- You would then set NextSprite[43]:=177; NextSprite[177]:=111 and
- NextSprite[111]:=43 (don't forget this final value!) to do so.
-
- Note (!) : - Most often, you will have the situation that some sprite(load)-
- numbers with consecutive numbers should make up a cycle. In that
- case it is more convenient to use the SetSpriteCycle()-procedure
- to do the job for you
- - Again, note that the routine deals with spriteLOADnumbers! That
- is intentionally, because a sprite cycle is related to the
- _physical_ existent sprite data, or simply spoken: if you make
- 5 pictures to form a flickering torch and you are going to use
- 10 torches in your animation then each of them should loop
- through this 5-picture-cycle, shouldn't it?
- - NextSprite[] is initially set "to point to itself", that is:
- NextSprite[i]=i for all possible i's. If you had to break off
- a sprite cycle (though I can't think what this should be good
- for...), you must restore this data, e.g.: if you wanted to
- break the sprite cycle above, you would have to set
- NextSprite[43]:=43; NextSprite[177]:=177; NextSprite[111]:=43;
- - As this is a global variable, AniVGA can't check whether your
- settings make sense or not; thus, it remains your responsibi-
- lity to use proper values!
-
- See also : SetSpriteCycle, Sprite cycles
-
-
- NMAX - constant
- ───────────────
-
- Function : Determines the maximum of sprites to be active at the same time
- (minus 1)
-
- Declaration: CONST NMAX=499
-
- Description: This constant sets the size of the internal tables - and thus the
- valid sprite numbers: the indices of the tables SpriteX, SpriteY
- and SpriteN must lie in the range 0..NMAX.
- To state it otherwise, there may be up to NMAX+1 sprites creeping
- around your screen at the same time...
-
- Note : Don't confound that constant with LoadMAX
-
- See also : LoadMAX
-
-
- OutTextLength - function
- ────────────────────────
-
- Function : Computes the length of a string in pixels
-
- Declaration: FUNCTION OutTextLength(s:STRING):WORD; FAR;
-
- Description: Fonts in AniVGA may be proportional spaced, so it could be hard
- to compute the length of a string. This function does exactly
- that: it computes the length of string "s" and takes care of
- proportional font widths and the like.
-
- Note : - Unlike CRT.Length, this function returns the length in _pixels_
-
- See also : FontWidth, FontWidthTable
-
-
- OutTextXY - procedure
- ─────────────────────
-
- Function : Writes a textstring to the graphic screen
-
- Declaration: PROCEDURE OutTextXY(x,y:INTEGER; pa:WORD; s:STRING); FAR;
-
- Description: Besides a built-in monochrome font, each character consisting of
- 6x6 pixels (small, but very ugly...), AniVGA has the capability
- to load font files from disk, either monochrome or colored fonts.
- To write the string "s" to the graphic screen, you must specify
- the upper left starting corner of the text in (x,y):
- (x,y) -> ▄──────────┐ , where (x,y) are virtual coordinates!
- │ │
- │ │
- │ │
- └──────────┘
- The text will be drawn in color GRAPHTEXTCOLOR and with the orien-
- tation GRAPHTEXTORIENTATION ("VERTICAL" or "HORIZONTAL").
- A third global variable, GRAPHTEXTBACKGROUND, specifies the color
- which will be used for the background area "beneath" the text
- letters with monochrome fonts (of course, colored fonts determine
- their pixel's colors themselves);
- if GRAPHTEXTCOLOR=GRAPHTEXTBACKGROUND then the text will be drawn
- like TurboPascal's routine does: only the pixels belonging to the
- letters will be drawn, all others remain unchanged.
- This also is the only exception valid for colored fonts, too:
- pixels with color 0 are treated the same way: if GraphTextColor=
- GraphTextBackground, then they won't be drawn, else they will be
- drawn (with GraphTextBackground as color value).
- "pa" specifies the graphic page to be drawn on and must be one of
- the drawing pages (0 or 1) or the BACKGNDPAGE (=2) for background
- mode STATIC. (For special purposes, SCROLLPAGE (=3) will work,
- too)
-
- Note : - In 99% of all cases, you will output text to the visible
- screen, that is: "OutTextXY(someX,someY,1-PAGE,'foobar')"
- - Any text drawn to the working pages 0 or 1 will stay onscreen
- only for one animation cycle. If you want it permanent, then
- use BackGroundOutTextXY() in mode STATIC or replace any call
- to Animate() by the sequence
- Animate();
- OutTextXY(someX,someY,1-PAGE,my_text)
- which works in both modes STATIC & SCROLLING. (As always, if
- you are in mode SCROLLING and use absolute coordinates, the
- text will scroll with your graphic image, while if you use
- relative coordinates (relative to StartVirtualX|Y of course),
- then the text will stay at a definite physical monitor position.
- For example,
- OutTextXY(StartVirtualX,StartVirtualY,1-PAGE,'Hi!')
- will tie the text to the upper left screen position)
- - Possible ERROR-values returned are: Err_InvalidPageNumber
-
- See also : GraphtextColor, GraphtextOrientation, GraphtextBackground,
- BackgroundOutTextXY
-
-
- PAGE - variable
- ───────────────
-
- Function : Holds the number of the actual drawing page
-
- Declaration: VAR PAGE:WORD
-
- Description: AniVGA uses a page flipping approach. Basically this means that it
- alternates between using page 0 and page 1 for its display.
- Although this mechanism should be transparent for the user, AniVGA
- provides you with the page number of the actual drawing page in
- "PAGE". Note that this number specifies always the invisible page:
- when PAGE=0, then the actual _displayed_ page is page 1 and vice
- versa (AniVGA always works on the invisible page!).
-
- Note (!) : Only _read_ this value, never assign a new value to it!
-
-
- PAGEADR - variable
- ──────────────────
-
- Function : Holds the segment address of the actual drawing page PAGE
-
- Declaration: VAR PAGEADR:WORD
-
- Description: As already mentioned, there are four graphic pages, numbered from
- 0 to 3. The start addresses of these four pages are used by AniVGA
- and normally the user should not need to reference them, but with
- PAGEADR at least the address of the actual (invisble) graphic page
- PAGE is available in PAGEADR.
-
- Note (!) : Only use this variable to _read_ its value, never change it!
- Although this 16-bit-value represents only the segment part of the
- complete address, it is the whole address: the address is norma-
- lized in such a way that the offset part is always zero.
-
- See also : PAGE
-
-
- PageGetPixel - function
- ───────────────────────
-
- Function : Returns the color value of the specified point
-
- Declaration: FUNCTION PageGetPixel(x,y:INTEGER; pa:WORD):BYTE; FAR;
-
- Description: If the point at the virtual coordinates (x,y) and graphic page
- "pa" lies on the screen (i.e.: in the range (0,0)..(319,199) in
- absolute coordinates), this routine will return its color, if it
- is offscreen, the function returns zero.
- "pa" should be one of the values 0, 1 or BACKGNDPAGE (=2). (For
- special purposes, SCROLLPAGE (=3) will be accepted, too)
-
- Note : - If you want to read a pixels' color from the _visible_ page, you
- have to remember that it is the opposite of the _actual_ page
- (that is, you have to use "1-PAGE" as page number).
- - Although only values of 0, 1, BACKGNDPAGE (=2) and SCROLLPAGE
- (=3) make sense as "pa" values, the routine doesn't check that
- (for improved speed)
- - For that, the routine _doesn't_ return Err_InvalidPagenumber or
- something similiar in ERROR!
-
- See also : Background, Coordinates, GetPixel
-
-
- PagePutPixel - procedure
- ────────────────────────
-
- Function : Plots a point at a specified page
-
- Declaration: PROCEDURE PagePutPixel(x,y:INTEGER; color:BYTE; pa:WORD); FAR;
-
- Description: This routine is very similiar to PutPixel(), but it lets you
- specify explicitly on which graphic page the point shall be drawn.
- (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its absolute
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- specified page "pa", which must have one of the values 0, 1,
- BACKGNDPAGE (=2) or SCROLLPAGE (=3). The latter ones only make
- sense if STATIC is used as background mode.
-
- Note : - Don't forget that this routine works with virtual coordinates.
- - Note also that the point is _not_ drawn automatically on the
- background page if pa=0 or pa=1, thus it will be visible exactly
- one animation cycle (and be overdrawn by the background image
- then).
- - Because of AniVGA's working scheme, you probably want to use
- this routine AFTER calling Animate() (else, your point would be
- overdrawn by the background image immediately) if pa=1-PAGE.
- If you want to draw the point at the _visible_ page, remember
- that it is the "opposite" of the _actual_ drawing page, i.e.:
- you have to use "1-PAGE" for "pa".
- - For improved speed, the routine _doesn't_ check the "pa"
- variable to have a valid value, so there will be no report to
- ERROR (Err_InvalidPageNumber or the like) available!
- It remains your responsibility to assure a proper value for pa!
-
- See also : BackgroundPutPixel, PutPixel, coordinates, How AniVGA works
-
-
- Palette, PaletteEntry, PalettePtr - type
- ────────────────────────────────────────
-
- Function : Supplies user with proper internal data types
-
- Declaration: TYPE PaletteEntry=RECORD red,green,blue:BYTE END;
- Palette=ARRAY[0..255] OF PaletteEntry;
- PalettePtr=^Palette;
-
- Description: Drawing colors with the EGA/VGA is quite an interesting thing!
- You probably heard that "mode $13 gives you 256 out of 262144
- colors". The key to this is the palette (or, to be precise:
- the color-look-up-table "CLUT").
- Every color (in the range 0..255) is used as a pointer into the
- CLUT; the corresponding entry consists of three bytes, which
- stand for the red/green/blue intensity of that color (in that
- order!). These three "bytes" (only the values 0..63 are valid for
- each of them) together form an "PaletteEntry". Because we have
- 256 colors, a complete CLUT is made of 256 such entries: such a
- table will be called a "Palette" in AniVGA!
-
- Note : AniVGA initially assumes the default colors of mode $13.
- When you change the palette and you are using one of the display
- modes Display_SHADOW or Display_SHADOWEXACT, AniVGA must know
- this, as it must recompute its ShadowTab. "SetPalette()" takes
- care of this, so you shouldn't change palettes by other means
- than "SetPalette()" until you are absolutely sure what you are
- doing!
-
- FYI: Note also that the 256 color modes are something special:
- in all other graphic modes (the EGA's 640x350x16 for example),
- there is a second, intermediate indirection level.
- There, the color value is used as an index into a table, giving
- a value between 0..63. This value is used again as an index into
- a second table which holds the triples ("PaletteEntries")
- mentioned above. The first table is called the palette, the second
- is the CLUT. In the 256 color modes, only the CLUT is used, but
- few of us ever heard of CLUTs! Because there is no way to confuse
- things in AniVGA, I decided to use the term "palette"!
-
- See also : SetShadowTab, ShadowTab, DefaultColors, SetPalette, GetPalette
-
-
- Palette (*.PAL) files - information
- ───────────────────────────────────
-
- Palette files generated by GRAB and MAKES make it possible to use different
- colors than the BIOS default values, just by issuing a LoadPalette()-call.
- Their internal format is the simplest possible: each color consists of three
- bytes, specifying the RGB-values (in that order), where each value can reach
- from 0 (darkest) to 63 (brightest), e.g.: a bright red would be coded as
- (63,0,0).
- LoadPalette() reads in a complete palette - equally, if it is 3*16 bytes in
- size or the max. 3*256 bytes for a complete 256 color palette, but it is wise
- to use complete 256 color palettes, because otherwise you soon get confused,
- - don't say I didn't warn you!
-
- See also : LoadPalette(), Palette
-
-
- PutImage - procedure
- ────────────────────
-
- Function : Pastes a formerly copied image to the screen
-
- Declaration: PROCEDURE PutImage(x,y:INTEGER; p:POINTER; pa:WORD); FAR;
-
- Description: PutImage() is the counterpart of GetImage(): use GetImage() to
- copy part of the screen and PutImage to paste it somewhere. (x,y)
- is the upper left corner of the destination (in _virtual_ coordi-
- nates), "p" is the pointer given by GetImage() and "pa" is the
- number of the graphic page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE
- (=3)) of the destination.
- If p equals NIL, the routine does nothing at all; this is useful
- because you can PutImage() directly on the result of a GetImage()
- call without further checking for clippings, although you should
- be careful by doing so: you don't get a "handle" this way which
- you could use to free up the occupied memory again!
- (See FreeImageMem() for more about that)
-
- Note : - Like GetImage(), this routine also works only when the _virtual_
- coordinates translate into _absolute_ coordinates in the range
- of 0..319, 0..199, that is: they must lie on the visible part of
- the screen, everything else is clipped off.
- - Possible ERROR-values returned are: Err_InvaliPageNumber
-
- See also : GetImage, FreeImageMem, coordinates
-
-
- PutPixel - procedure
- ────────────────────
-
- Function : Plots a point
-
- Declaration: PROCEDURE PutPixel(x,y:INTEGER; color:BYTE); FAR;
-
- Description: (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its absolute
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- visible page 1-PAGE.
-
- Note : This routine is not the same as TurboPascal's one: it works with
- virtual coordinates! Note also that the point is _not_ drawn on
- the background page, thus it will be visible for exactly one ani-
- mation cycle (and be overdrawn by the background image then).
- Because of AniVGA's working scheme, you probably want to use this
- routine AFTER calling Animate() (your point will then be visible
- until the next call to Animate()).
-
- See also : BackgroundPutPixel, PagePutPixel, coordinates, How AniVGA works
-
-
- PutTile - procedute
- ───────────────────
-
- Function : "Pastes" a tile into the background image
-
- Declaration: PROCEDURE PutTile(x,y:INTEGER; TileNr:BYTE); FAR;
-
- Description: After you have defined a background scrolling area, you can use to
- PutTile() to arrange them as wanted to build your background image.
- (x,y) is the virtual coordinate where you want the tile "TileNr"
- to be placed.
- (x,y) will be changed to be a multiple on 16 in each direction
- and must then lie in the range (BackX1,BackY1)..(BackX2,BackY2).
-
- Note : - Of course, this routine only makes sense when you use background
- mode SCROLLING!
- - (x,y) will be drawn to the upper left to fall on the grid.
- - Possible ERROR-values returned are: Err_InvalidCoordinates
-
- See also : background, tile, SetBackgroundScrollRange, coordinate, BackX1,
- BackX2, BackY1, BackY2, GetTile
-
-
- Screen - procedure
- ──────────────────
-
- Function : Chooses the display page.
-
- Declaration: PROCEDURE Screen(pa:WORD) FAR;
-
- Description: Call Screen() with a value between 0 and 3 which tells the routine
- to which graphic page it should switch. This is done by repro-
- gramming the VGA start address registers. For a flickerfree dis-
- play, this switching is synchronized to the display enable signal.
-
- Note (!) : - You should not use this routine if you are not absolutely sure
- what you are doing! Be aware that AniVGA relies on the fact that
- the actual drawing page is PAGE and its segment address is in
- PAGEADR while the actually visible page is 1-PAGE!
- - Although it makes little sense to apply this routine to graphic
- pages other than 0 or 1, it is possible to set "pa" to 2 (=BACK-
- GNDPAGE) or 3 (=SCROLLPAGE).
-
- See also : PAGE, PAGEADR, InitGraph
-
-
- ScrollPage - constant
- ─────────────────────
-
- Function : Holds the page number of the backround page
-
- Declaration: CONST SCROLLPAGE=3;
-
- Description: When using background mode SCROLLING, BackGndPage specifies the
- page number of the tile buffer used to build up the background
- image for animations.
-
- Note (!) : - Use of this constant only makes sense when using background
- mode SCROLLING!
- - AniVGA allows to treat pages 2 and 3 (=BACKGNDPAGE and
- SCROLLPAGE) as normal graphic pages. This is convenient for the
- advanced user who wants to play special tricks on AniVGA (the
- routine IntroScroll() is an example for this).
- However, you should not forget, that *normaly*, pages 2 and 3
- have a special purpose in AniVGA and shouldn't be used by you.
-
- See also : BackGndPage, Background, IntroScroll
-
-
- SetAnimateWindow - procedure
- ────────────────────────────
-
- Function : Restricts animations to a screen window
-
- Declaration: PROCEDURE SetAnimateWindow(x1,y1,x2,y2:INTEGER); FAR;
-
- Description: By default, the complete screen is set to display animations
- (this is equivalent to SetAnimateWindow(0,0,XMAX,YMAX) ).
- By using this procedure, you may restrict animations to a
- smaller "window" of your screen: (x1,y1) and (x2,y2) are the
- upper left and lower right corner of this window, specified
- as *absolute* coordinates of course.
- The best way to imagine the functionality is this: think of a
- black sheet of paper, 320x200 units in size, covering your
- monitor display. SetAnimateWindow() cuts a hole in this paper
- so that you may look through it to see the animations taking
- place at the screen. The resting parts of that sheet remain
- completely untouched by AniVGA and under your responsibility.
- Line- and pixeldrawing routines may restrict ("clip") their
- outputs to this animation window --you can control that by
- using the boolean variable "WinClip".
- If for some reason you want some sprites _not_ to be clipped,
- you may use SetSplitIndex() to tell AniVGA which sprites should
- be clipped and which should not.
-
- Note (!) : - As said, the window is defined with absolute coordinates
- - Its boundaries must meet some restrictions: x1 and the window
- width itself (=x2+x1-1) must be multiples of 4 and the window
- must be at least 32x32 points in size.
- - The routine tries to round the coordinates given appropriately
- and reflects the chosen values in WinXMIN, WinYMIN, WinWidth and
- WinHeight. (If it fails, you will get an Err_InvalidCoordinates
- error).
- - Due to this rounding effects, rely upon the Win* variables
- instead of the original values you gave to the routine
- - This routine works with both STATIC and SCROLLING backgrounds!
- Although its use is more obvious with SCROLLING backgrounds, it
- makes sense to use it in mode STATIC, too: by making the area to
- to be cared about smaller, AniVGA may become faster.
- - Don't confuse this routine with SetBackgroundScrollRange()!
- SetAnimateWindow() defines what part of your (real) monitor
- shall be treated as window to your animations while
- SetBackgroundScrollRange() is a routine for background mode
- SCROLLING to define which virtual area of the coordinate space
- shall be used for tiling!
-
- See also : UpdateOuterArea, Win*, SetSplitIndex
-
-
- SetBackgroundMode - procedure
- ─────────────────────────────
-
- Function : Chooses one of the possible background modes of AniVGA
-
- Declaration: PROCEDURE SetBackgroundMode(mode:BYTE); FAR;
-
- Description: AniVGA has two possible ways of handling background you can choose
- of: "STATIC" or "SCROLLING" backgrounds with several advantages
- and disadvantages, each (see background). Specify the mode you
- want to use in the "mode" variable.
-
- Note : - Default value set by AniVGA is STATIC.
- - Possible ERROR-values returned are: Err_InvalidMode
-
- See also : background
-
-
- SetBackgroundScrollRange - procedure
- ────────────────────────────────────
-
- Function : Specifies the scrollable background area in mode SCROLLING
-
- Declaration: PROCEDURE SetBackgroundScrollRange(x1,y1,x2,y2:INTEGER) FAR;
-
- Description: (x1,y1) is the upper left corner of the background scroll area,
- (x2,y2) the lower right corner (all virtual coordinates).
- AniVGA will round the points given to fit on a grid with mesh 16,
- that is, x1,y1,x2,y2 will be changed to be all multiples of 16.
- These new values will be stored in the (global) variables BackX1,
- BackY1, BackX2, BackY2 for further use.
- Besides that, XTiles and YTiles will hold the width and height of
- the choosen background area in tiles.
-
- Note : - You can read the Back??-variables for your information, but
- don't change them!
- - Of course, this routine only makes sense when you are going to
- use SCROLLING as background mode.
- - The upper left corner (x1,y1) will be dragged to the upper left,
- the lower right corner (x2,y2) to the lower right to fall on the
- grid.
- - Don't forget that the tile memory is limited; you can't select
- an area bigger than MaxTiles (=10000) tiles, that is more than
- 2560000 pixels².
- - Possible ERROR-values returned are: Err_InvalidCoordinates and
- Err_BackgroundToBig
- - Don't confuse this routine with SetAnimateWindow()
-
- See also : background, tiles, PutTile, SetAnimateWindow
-
-
- SetCycleTime - procedure
- ────────────────────────
-
- Function : Defines the maximum animation speed
-
- Declaration: PROCEDURE SetCycleTime(milliseconds:WORD); FAR;
-
- Description: There are lots of PC-compatible machines with a broad range of
- clock rates, wait states and different speeds of their graphic
- cards. With this routine you can set the time an animation cycle
- has to last at least: at the very end of Animate, the routine
- checks whether at least "milliseconds" milliseconds have been past
- since the last call to this routine and waits if necessary.
- If you give 0 milliseconds as an argument or your machine is not
- (at least) an AT class machine, there will be no such time control
- mechanism and the animation will always take part at the maximal
- speed on the specific machine (this is also the default value).
-
- For example: "SetCycleTime(100);" would restrict the animation
- rate even on the fastest 80586 machines to at most 1sec/100msec
- = ten frames per second.
-
- Note (!) : - Because there is no such high precision timer on PC/XT computers
- as required, SetCycleTime() is ignored on these machines.
- Anyway, this should be not to hard because these computers are
- normally that slow that they would not have been slowed down
- either.
- - The accuracy of this timing mechanism is better than 1 milli-
- second.
-
-
- SetModeByte - procedure
- ───────────────────────
-
- Function : Specifies the way a sprite will be displayed
-
- Declaration: PROCEDURE SetModeByte(Sp:WORD; M:BYTE); FAR;
-
- Description: This routine assigns one of the possible display methods "M"
- (Display_NORMAL, Display_FAST, Display_SHADOW,
- Display_SHADOWEXACT)
- to the specified spriteLOADnumber "Sp".
-
- Note : - Because this kind of information is stored directly inside the
- sprite data, the sprite must have been loaded already for this
- routine to work.
- - For the same reason, the routine works on spriteLOADnumbers,
- not sprite numbers (>gee, again!<): a display method set for one
- spriteLOADnumber will affect all sprites with that LOADnumber!
- Most often, that is okay (e.g.: if you use the sprite of a foot-
- ball player ten times, it is quite normal to use the same dis-
- play mode for all ten players!), if you really must use a sprite
- with two different display methods at the same time, you can use
- the following trick: load the sprite's data a second time into
- memory, using a different spriteLOADnumber. For this new copy,
- you can use another display mode.
- - Possible ERROR-values returned are: Err_InvalidSpriteNumber and
- Err_InvalidMode
-
- See also : SpriteLoadNumber, SpriteNumber, Display methods, GetModeByte
-
-
- SetOffscreenTile - procedure
- ────────────────────────────
-
- Function : Defines the tile to be used outside the specified scroll range
-
- Declaration: PROCEDURE SetOffscreenTile(TileNr:BYTE); FAR;
-
- Description: When you use background mode SCROLLING and have set up a scroll
- range (via SetBackgroundScrollRange() ), all tiles _within_ that
- region are specified by your settings done with PutTile().
- However, AniVGA must know what to draw when it has to display
- areas _outside_ that "window": you can choose that tile with
- SetOffscreenTile().
- Example: You set your scrollable background range by issuing
- SetBackgroundScrollRange(-500,-500,1000,1000) and used PutTile()
- to define that tiles 0..10 (say) should be used inside that
- window (-500,-500,1000,1000) in some specific order. If you want
- that everything outside the window should be painted with tile
- 6 (say), you would tell AniVGA so by calling SetOffscreenTile(6)
-
- Note : - The default value set by AniVGA is 0
- - Of course, using this procedure only makes sense when using
- background mode SCROLLING!
-
- See also : SetBackgroundScrollRange, PutTile, Background
-
-
- SetPalette - procedure
- ──────────────────────
-
- Function : Changes the VGA's color values
-
- Declaration: PROCEDURE SetPalette(pal:Palette; update:BOOLEAN); FAR;
-
- Description: You can use this procedure to change the color values of the VGA's
- 256 colors by supplying an appropriate palette.
- "update" tells the procedure whether it should recompute its
- internal "ShadowTab" or not; if you use one of the two display
- modes Display_SHADOW or Display_SHADOWEXACT you must set this
- value to TRUE or the shadow areas will show "wrong" colors
- (namely the old ones *before* changing the palette). If you don't
- use shadowing (or change colors in a way so that using the old
- shadow is okay), you can use FALSE and save some time.
-
- Note : - SetPalette automatically updates "ActualColors" to reflect the
- changes made; although you don't have to use the variable
- "ActualColors" as first parameter of this procedure, you are
- recommended to do so, that is
- a) make your color changes to ActualColors[]
- b) call SetPalette(ActualColors,TRUE|FALSE)
- This way, you will save some time and the memory requirements
- for an additional palette
- - If you messed up things, use "SetPalette(DefaultColors,TRUE)" to
- return to the default values.
- - You must be in graphic mode already or strange things may happen
- (at least, you won't get the colors you intented...)
- To state in otherwise: call this routine _after_ having called
- InitGraph() and _before_ calling CloseRoutines()!
-
- See also : GetPalette, Palette, LoadPalette, ActualColors
-
-
- SetShadowTab - procedure
- ────────────────────────
-
- Function : Set the amount of shadowing in display modes Display_SHADOW and
- or Display_SHADOWEXACT
-
- Declaration: PROCEDURE SetShadowTab(brightness:BYTE); FAR;
-
- Description: Whenever a sprite is drawn in Display_SHADOW / Display_SHADOWEXACT
- mode, AniVGA must know how much darker these shadow areas should
- be, compared with the brightness of the original (not-shadowed)
- colors.
- This data is held in the table ShadowTab and is set by default to
- 70% of the colors original brightness. However, you can use this
- routine to provide more or less darker shadow areas: "brightness"
- is the percentage of the colors original brightness which shall
- remain, e.g.: brightness=0 would mean every shadow is completely
- black, brightness=100 is the original color as shadow (not darken-
- ed at all), brightness=40 will darken every color by 100-40=60%,
- etc.
-
- Note (!) : - SetShadowTab() bases its computation on the actually displayed
- colors, held in the table "ActualColors"
- - This routine takes app. 1s on an 8MHz AT. This can be quite a
- "long" time when you are in midst of a smooth animation sequence
- -or doesn't bother you at all (e.g., in the very beginning of
- your program) - this depends on your applications!
- - The argument will be only approximated: the algorithm computes
- the 256 color values needed precisely and matches them as close
- as possible to the 256 colors actually set.
- Note that the palette registers of the VGA card *won't* be
- changed at all! AniVGA still works with the default VGA palette
- of the BIOS (or whatever values you set); what it does is
- solely creating an internal color look-up-table!
- - Possible ERROR-values returned are: Err_InvalidPercentage
-
- See also : ShadowTab, ActualColors, Display modes, SetModeByte
-
-
- SetSplitIndex - procedure
- ─────────────────────────
-
- Function : Define which sprites should be clipped to the animation window
-
- Declaration: PROCEDURE SetSplitIndex(number:INTEGER); FAR;
-
- Description: If you defined an animation window (using SetAnimateWindow() ),
- all sprites will automagically be clipped properly at the
- boundaries of this window. However, you may think of a few
- situations where you want to disable this clipping, so you can
- draw a sprite _outside_ the animation window.
- You can telling AniVGA which sprites should be clipped and which
- should not by using SetSplitIndex(number): all sprites
- SPRITEN[0..number] will not be clipped to the window and
- SPRITEN[number+1..NMAX] will still be clipped
- To turn on clipping for all sprites again, just call this
- procedure with an argument <0 or >NMAX
-
- Notes : - Default value is: all sprites clipped
- - Of course, clipping at the *physical* screen boundaries won't
- be affected in any way!
-
- See also : SetAnimateWindow, WinClip
-
-
- SetSpriteCycle - procedure
- ──────────────────────────
-
- Function : Link spriteLOADnumbers together to form a sprite cycle
-
- Declaration: PROCEDURE SetSpriteCycle(nr,len:WORD); FAR;
-
- Description: "nr" is the first spriteLOADnumber to be included in the sprite
- cycle and "len" entries (i.e.: from "nr" to "nr+len-1") should be
- tied together.
- The routine will then set the according NextSprite[] entries to
- build this cycle: nr -> nr+1 -> nr+2 -> ... -> nr+len-1 -> nr
-
- Note : - The routine uses spriteLOADnumbers, _not_ sprite numbers!
- - If you want to link sprite(loadnumber)s which do not have conse-
- cutive (load)numbers, you must do that by setting NextSprite[]
- accordingly.
-
- See also : Sprite cycles, NextSprite
-
-
- ShadowTab - "procedure"
- ───────────────────────
-
- Function : Table for translating sprite colors into others
-
- Declaration: PROCEDURE ShadowTab; FAR;
-
- Description: If the display mode "Display_SHADOW" is set for a physical
- sprite, its colors will depend not on the values stored in the
- sprite itself, but on the values found on the screen at the place
- where the sprite shall be drawn: every pixel of the sprite will
- become darkened by substituting its corresponding color against
- the color stored in this color table. (Mode "Display_SHADOWEXACT"
- behaves the same, but shadowing will take place only at points
- with sprite color <>0 - that's the whole difference).
- At startup, this table is set to make shadows be approximately
- 70% the brightness of the original colors, but you can adjust
- this with the routine SetShadowTab() if this value is not sui-
- table for your application.
- You can even supply a completely different color table (for
- special effects?).
- To do so, define an array "[0..255] of byte" (you should use the
- predefined TYPE ColorTable for this), containing for each color
- of the standard palette its substitute (e.g. setting array
- element [8]:=13 would mean: "replace every pixel in the shadow
- area with color 8 against a pixel with color 13") and overwrite
- the original color table by issuing the command
- "MOVE(my_array,@ShadowTab^,256)"
-
- Note : - Although this table is declared as a procedure, it really is
- data, not code; so don't call it!
- - There can be only _one_ color table and it is only active in
- display modes "Display_SHADOW" or "Display_SHADOWEXACT".
-
- See also : SetShadowTab, Display modes, SetModeByte
-
-
- SHOWPIC - utility
- ─────────────────
-
- This is a _very_ small utility program to display a *.PIC-file on the screen.
- (As a matter of fact, someone asked for a way to do so and as it could be
- done that easily, I just couldn't resist typing it in... :) )
- Call the program with the complete name of the *.PIC-file to display and
- (optionally) the name of the palette file to be used as second parameter.
- If you omit the palette file name, the program will use the VGA's default
- palette.
- Example: "SHOWPIC FRACTAL1.PIC FRACTAL.PAL" would load the picture
- FRACTAL1.PIC and use the palette FRACTAL.PAL to display it.
- Press any key to return to text mode again.
-
- See also : MAKES
-
-
- SPRITE, Spritenumbers, Spriteloadnumbers - information
- ──────────────────────────────────────────────────────
-
- A sprite is the basic data element used in AniVGA. Technically spoken, it is
- nothing more then a two-dimensional array of bytes which becomes copied to the
- screen positions needed, but it is far more comprehensive to think about it as
- a photograph of a figure which can be pasted to the screen whereever you want.
- To distinguish between different sprites, we use natural numbers, but whenever
- we talk about "sprites", we are somehow inaccurate:
- You should notice that there are two kinds of "sprite numbers" which should
- not be mixed up: one is a spriteLOAD number and represents a handle to the
- (physical) sprite data, while the other (normally termed "sprite number") is
- a logical number to address the sprite data.
- Yet, most often it is clear from the context, which meaning is intended:
- For a simple example: if you are going to animate a soccer team, you would
- need 11 sprites for the player - but they all have the same shape. This means,
- you only have to load one sprite (-> you need 1 spriteLOAD number), but need
- 11 copies of that image to move around the screen (-> you need 11 sprite
- numbers).
- (See section "How AniVGA works" for more about that)
- You can design sprites with the help of the spritemaker-tool MAKES, by using
- GRAB to capture and convert graphic screens from other graphic applications
- or write your own tools for that (it's really not that difficult you think
- it is...).
-
- See also : sprite format, How AniVGA works
-
-
- SPRITE CYCLES - information
- ───────────────────────────
-
- Often, you don't want to have a single picture as sprite, but a sequence of
- them which should loop forever. For example, let's assume that you use a torch
- as an animation object in your application and you want it to have a flicker-
- ing flame.
- You would start to draw 5 (say) pictures, which -repeatedly displayed one
- after another- would make the impression of your flickering torch. But within
- your application, you still want to handle these five different images as one
- single object - namely the sprite "torch".
- To do so, you can use a capability of AniVGA, called a "sprite cycle": load
- the five images as (physical) sprites and tie their loadnumbers together to
- form that sequence!
- The easiest way to do that would be to load the images with consecutive
- numbers and use the SetSpriteCycle() procedure to form the sprite cycle (see
- there).
- Note that we are talking about linking spriteLOADnumbers here: when you have
- built such a cycle for your torch and you want to use 10 torches in your
- program, you surely want that each of them behaves the same, that is: they all
- should show a flickering flame by using that sprite cycle.
- For this reason, AniVGA uses spriteLOADnumbers, so that every instantiation of
- a spriteLOADnumber (i.e.: a SpriteN[]-entry) belonging to a cycle will lead to
- a sprite cycle for this sprite! (Tip: in out torches example, it would be wise
- to use different starting values for the 10 torches, so that they do not
- flicker "in phase")
- A small detail at last: if you defined a sprite cycle to be a->b->c->a->...,
- and initialized a SpriteN[]-entry to "a", then the first sprite displayed at
- the screen will be "b" instead of "a" - why?
- Well, AniVGA handles sprite cycles in the Animate() routine and thus has two
- possibilities to update the SpriteN[]-table (by issuing a "SpriteN[] :=
- NextSprite[SpriteN[]]" command): _before_ drawing the sprites or _afterwards_.
- But when it does _after_ drawing the sprites, the sprites displayed on your
- screen (=the old SpriteN[] values before doing the above command) are incon-
- sistent to the according numbers actually held in the SpriteN[]-table!
- This could lead to problems (e.g.: when you do a HitDetect() after calling
- Animate()). Although this could be circumvented by a special grouping of sub-
- routine calls, it is far more convenient to update the SpriteN[]-table
- _before_ drawing the sprites.
- The only drawback with this method is the one stated in the beginning: not the
- SpriteN[]-entry supplied by you will be drawn, but its "successor"
- NextSprite[SpriteN[]]!
- However, most often that won't be that bad and *if* it would, you still could
- compensate for it by using the sprite's predecessor (in the above example, you
- would use "c", as it is the predecessor of "a", to display "a").
-
-
- SPRITE FORMAT - information
- ───────────────────────────
-
- As already said, a sprite is nothing more then a two-dimensional array of
- bytes which becomes copied to the screen positions needed.
- For quick animations, the data should be stored in a format which causes few
- and simple transformation steps when accessing the data, but it is hard to
- keep up with that principle, because the graphic mode used is "planed".
- This means that points are _not_ stored sequentially into the graphics memory,
- but in a rather strange way: every 4 points use the same address, but lie in
- different "bitplanes". To cut it short: clipping and drawing sprites is hell
- therefore (and surely one reason why there are so less tools for this mode)
- and AniVGA uses a very special format to store a sprite (= *.COD-files):
-
- 0..1 DW offset to Plane_0_Data (points with x-coord. MOD 4=0)
- 2..3 DW offset to Plane_1_Data (points with x-coord. MOD 4=1)
- 4..5 DW offset to Plane_2_Data (points with x-coord. MOD 4=2)
- 6..7 DW offset to Plane_3_Data (points with x-coord. MOD 4=3)
- 8..9 DW sprite width (DIV 4), rounded up if not dividable by 4
- 10..11 DW sprite height in lines
- 12..15 DB 1,2,4,8 ; constants (translate-table)
- 16..17 DW SpriteLength ; length of this sprite file
- 18..37 DW 10 dup(?) ; reserved area for future use
- 38..39 DB 'K','R' ; code for "this is a sprite file"
- 40 DB 1 ; version
- 41 DB 0 ; default display mode (0=Display_NORMAL)
- 42..43 DW offset pointer to left boundary table
- 44..45 DW offset pointer to right boundary table
- 46..47 DW offset pointer to top boundary table
- 48..49 DW offset pointer to bottom boundary table
- 50..SpriteLength-1: boundary- and plane data tables
-
- (If you should wonder why all pointers are only 16 bit long: the maximal size
- of one sprite is 64k, so offset pointers are sufficient.
- Another trick is that AniVGA loads sprites at segment boundaries; for that,
- you don't have to distinguish between "relative offsets" and "offset poin-
- ters": if normalized segment addresses (=offset part is ε [0..15]) are used
- to address sprites, the offset part is always 0, so the two terms are
- identical!)
-
- The Plane_?_Data tables consist of the points of the sprite (1 pixel = 1 byte);
- if the sprite width is 12 pixels (say), then each table would hold 12/4=3 bytes
- for each of the sprite's rows:
- Plane_0_Data = color of pixels 0,4,8 of 1. sprite row
- color of pixels 0,4,8 of 2. sprite row
- ...
- Plane_1_Data = ditto, for pixels 1,5,9
- Plane_2_Data = ditto, for pixels 2,6,10
- Plane_3_Data = ditto, for pixels 3,7,11
-
- The boundary tables hold the outermost positions of the sprite:
- The left/top/right/bottom boundary table holds the leftmost/topmost/
- rightmost/bottomost pixel of each row/column/row/column (or 16000/16000/
- -16000/-16000 if none exists), respectively:
- left boundary table = leftmost pixel coordinate of 1. sprite row (or 16000)
- leftmost pixel coordinate of 2. sprite row (or 16000)
- ...
- Note that each entry in the boundary tables consists of a signed integer!
-
- Note also that sprites are always stored as the smallest, the figure including
- box (rounded up in the x-direction to the next multiple of 4), but that the
- values of the "superfluous points" stored in the plane tables doesn't matter
- at all (no difference which display mode is used for the sprite!), because
- AniVGA uses only the bytes of the areas which belong to the _real_ sprite-
- figure (AniVGA determines these parts by assuming the sprite to be "horizontal
- convex" and uses the boundary tables to compute them).
- (Don't worry if you do not understand these technical details now --hopefully,
- you won't need them at all).
-
- See also : MAKES, Display modes, convex, sprite library
-
-
- SPRITE LIBRARY - information
- ────────────────────────────
-
- Sprite files can be combined to sprite libraries. The main advantage of this
- is that you can reduce the number of files needed for your programs drama-
- tically:
- A normal program will use approximately 20..40 different sprites, so that you
- would have 20..40 files only for your sprites!
- But AniVGA's routine to load sprites "loadSprite()" is flexible enough to dis-
- tinguish whether the file to be loaded contains one or more sprites and loads
- them all.
- To construct such a "sprite library" (suggested filename extension: .LIB), you
- just use MSDos' COPY-command with the binary option "/B" to glue the binaries
- together; for example:
-
- COPY /B sprite1.cod+d:\sprites\sprite2.cod+testspr.cod A:\mylib.lib
-
- would concatenate the three sprites "sprite1.cod", "d:\sprites\sprite2.cod"
- and "testspr.cod" and build the sprite library "A:\mylib.lib".
-
- Note : You can reverse this process with the UNLIB-utility.
-
- See also : UNLIB, sprite format, loadSprite
-
-
- SpriteAd, SpriteSize, SpritePTR - variables
- ───────────────────────────────────────────
-
- Function : Store the pointers to the sprites' data and related informations
-
- Declaration: VAR SPRITEAD,SPRITESIZE:ARRAY[0..LoadMAX] OF WORD;
- VAR SPRITEPTR:ARRAY[0..LoadMAX] OF POINTER;
-
- Description: Whenever you load a (physical) sprite with LOADnumber xxx, AniVGA
- stores the sprite's data somewhere in RAM and maintains a pointer
- which points to the beginning of this data as a handle to access
- the data: this handle is stored in SpriteAd[xxx] and reflects the
- segment part of the starting address of the data.
- The address and length of the memory block allocated for the
- sprite's data are stored in SpritePTR and SpriteSize, respec-
- tively.
-
- Note : - These tables have been moved to the unit's implementation part
- in version 1.2 to prevent direct accesses, so consider this
- section as informational only.
- - The contents of the segment part of the SpritePTR[] entries
- will vary from the SpriteAd[] entries, because SpritePTR[]
- holds the pointer exactly in the form returned by TP's GetMem-
- procedure while SpriteAd[] stores them normalized and evtl.
- rounded to the next segment boundary. It's also that reason,
- why the allocated block is up to 15 bytes larger then theore-
- tical necessary
-
- See also : LoadSprite, SPRITE, Sprite Format
-
-
- SPRITEN, SPRITEX, SPRITEY - tables
- ──────────────────────────────────
-
- Function : Hold the values of all sprites to be drawn in the next animation
- cycle.
-
- Declaration: VAR SpriteN:ARRAY[0..NMAX] of Integer (SpriteX/Y dto.)
-
- Description: AniVGA is based on tables: in SpriteN[] you must declare, which
- sprites shall be drawn in the next animation step. To do that,
- store the spriteLOAD number of the sprites into the SpriteN[]-
- entries; a zero indicates that the according sprite is inactive
- and should not be displayed.
- For every active sprite (SpriteN[i]<>0), a pair of virtual coor-
- dinates in the range -16000..+16000 must be specified in the
- SpriteX[i] and SpriteY[i] entries to determine the sprites' po-
- sition on the (virtual) screen.
- These coordinates will be transformed internally into real coor-
- dinates to decide whether the sprite is onscreen and has to be
- displayed or not.
-
- Note : If you have less sprites than are allowed by the system (that is:
- less than NMAX+1), your decision what table entries you use are
- arbitrary; if for example you have only two sprites, it won't
- matter, if you use SpriteN[0] for the first one and SpriteN[1]
- for the other or vice versa, or SpriteN[123] and SpriteN[310] or
- whatever valid indices you can think of - except in one point:
- the sprites are drawn in reverse order, that means SpriteN[NMAX]
- is drawn first, then SpriteN[NMAX-1] ... SpriteN[0].
- For that, if two (or more) sprites overlap each other, the one
- with the smallest index is drawn topmost and covers the other(s).
-
- For performance reasons you should observe another rule: if you
- use different display methods for different sprites then try to
- group your sprites in such a way, that sprites with the same dis-
- play method have continous indices. As an example: if the sprites
- with (load)number 1 use one method and the ones with number 2
- another, then the sequence SpriteN[]=(...2,2,2,2,2,...,1,1,1...)
- would be better than (...2,2,1,2,...,1,2,...,1,2,...).
- This is due to the fact that whenever AniVGA has to draw a sprite
- with a display method other than the active one, it must inter-
- nally switch from one method to the other which costs some time.
-
- See also : SetModeByte
-
-
- StartVirtualX, StartVirtualY - variables
- ────────────────────────────────────────
-
- Function : Specify the upper left corner of the visible world
-
- Declaration: CONST StartVirtualX:INTEGER=0;
- StartVirtualY:INTEGER=0;
-
- Description: When working with virtual coordinates, your screen displays only
- a very small window (320x200 points) of this "virtual screen"
- (32000x32000 points). To tell AniVGA which part of this virtual
- screen is to be displayed, you specify the upper left corner of
- the visible part in (StartVirtualX,StartVirtualY).
- For example, setting (StartVirtualX,StartVirtualY) to (100,1000)
- would define that the part of the virtual screen having x-coordi-
- nates ε [100..100+XMAX] and y-coordinates ε [1000..1000+YMAX] to
- be displayed.
-
- Note : Setting these variables doesn't affect the HitDetect-function: if
- two sprites collide outside the visible area, it will be detec-
- ted, still.
-
- See also : coordinates
-
-
- Table - TYPE
- ────────────
-
- Function : Supply a data type for the animation variables
-
- Declaration: TYPE Table=ARRAY[0..NMAX] OF INTEGER;
-
- Description: A lot of variables in AniVGA have to be of type "one entry for
- each sprite" and "Table" is the appropriate form for that.
-
- Note : -
-
- See also : SpriteX, SpriteY, SpriteN
-
-
- Tile - information
- ──────────────────
-
- "Tiles" are graphic images, 16 pixels wide and high. They are used to define a
- scrollable background image when you use SCROLLING as background mode.
- Due to memory limitations, it is impossible to hold a complete background
- image in memory (because virtual coordinates range 32000 pixels in x/y-direc-
- tions, one would need app. 977 MB (!) RAM for that).
- Instead, you may define up to 256 different tiles and then combine them to
- form the graphic background, which may consist of up to MaxTiles (=10000)
- tiles (using the 256 different tiles).
- (A simple example for that can be found by "Background").
- AniVGA stores tiles in a slightly different format then sprites internally,
- but you don't have to bother your head about that: on disk, tiles have the
- same format as sprites, so you can use all the utility programs to create/edit
- sprites also to create/edit tiles! The only restriction you have to care about
- is, that a tile has the definite size of 16 pixels in each direction (but see
- the LoadTile()-function for some simplifications about even that).
-
- See also : Background, LoadTile
-
-
- UNCHAIN - utility
- ─────────────────
-
- AniVGA uses a graphics mode unknown to TurboPascal. In fact, TP "thinks" the
- mode used is BIOS mode $13 (=320x200x256x1). There is only one situation where
- this assumption causes problems: when you use TP's built-in debugger (or a
- standalone debugger like TD.EXE) to single-step or trace your program.
- Why? Well, your program runs in AniVGA's special graphic mode -up to the point
- where you stop it by some kind of breakpoint: the debugger switches to its
- text mode, displays the infos you wanted. But then you tell the debugger to
- continue the program and hence, it must switch back to graphics mode and
- BINGO! it switches to BIOS mode $13 instead of AniVGA's graphic mode.
-
- To avoid that behaviour, there is a (really) small PD utility program called
- "UNCHAIN.EXE". Simply stated, prefix the command line you normally use to
- invoke TP with "unchain" and that's it! For example, instead of...
- TURBO.EXE myprog.pas
- ...you would type in
- UNCHAIN TURBO.EXE myprog.pas
- Simple, ain't it? It works the same way for all other programs (TD.EXE, etc.)!
-
- Of course, you also have to enable the options "Graphics screen save" and
- "EGA/VGA palette save" in menu Options -> Environment -> Startup of TP, but
- I guess that goes without saying...
-
-
- UNLIB - utility
- ───────────────
-
- Sometimes, you will want to reverse the process of building a sprite library,
- that is: you want to split a sprite library into the sprite files of which it
- consists.
- To do that, call UNLIB with the name of the sprite library to split. UNLIB
- will then create the files UNLIB000.COD, UNLIB001.COD, UNLIB002.COD,... which
- represent the sprite files wanted.
- Note here that UNLIB cannot restore the original filenames you used (there is
- no such entry in a sprite's header). For that, it is a good idea to write down
- the names and sequence of the sprite files used in building a sprite library.
- (If you didn't, you still can load every extracted sprite with MAKES, look at
- it and give it the right name then)
-
- See also : sprite library, MAKES, sprite format
-
-
- UpdateOuterArea - variable
- ──────────────────────────
-
- Function : Specifies if and how to update graphic area outside the animation
- window
-
- Declaration: CONST UpdateOuterArea:BYTE=2;
-
- Description: If you have defined an animation window (using the
- SetAnimateWindow()-procedure), AniVGA by default only handles
- that graphic area. That is, whatever you do to the screen area
- *outside* your animation window, AniVGA doesn't care: if you
- draw some objects there, it's up to you to remove them from
- there later on.
- If you draw to the background image in BACKGNDPAGE (by using
- BackgroundOutTextXY() or similiar routines), the changes done
- will not be visible to the screen image until you tell AniVGA
- to update the outer area!
- Now quite often, you will stumble into this situation:
- - you have a background image in your background page,
- surrounding your animation window (1) with some fancy
- graphics (2)
- - you draw something into the outer area, for example a high
- score (3), using BackgroundOutTextXY()
- - 50 (say) animation cycles later, you realize that you want to
- get rid off the old contents drawn upon the outer area and
- replace it by something new:
- ┌───────────────────────┐
- │ outer area (filled │
- │ with background page) │
- │ ┌────────────┐ ▒▒▒ │
- │ │ animation │ ▒3▒ │
- │ │ window 1│ │
- │ └────────────┘ 2 │
- └───────────────────────┘
-
- To simplify that task, AniVGA checks the variable UpdateOuterArea
- each time Animate is called: if it is <>0, the area (2) becomes
- replaced by the respective contents of the background page and
- the variable is decremented by 1.
-
- Note (!) : - As AniVGA uses a page flipping scheme, you usually will set
- UpdateOuterArea:=2
- By that, AniVGA will update the screen area in the two next,
- successive calls to Animate, thus updating both visible pages
- - Of course, this routine will work with both possible background
- modes STATIC and SCROLLING
- - If you want to draw lines, pixels or text outside area 1, you
- must set WinClip:=FALSE to prevent AniVGA from automatically
- clipping!
- - Similiar, if you want to draw a sprite outside area 1, you
- must use SetSplitIndex() to tell AniVGA which sprites should
- not be clipped
- - You must use this variable whenever you painted something
- into the _background_ area and want to make it visible! This
- is especially true for BackgroundOutTextXY() and the like.
- Do not oversee that!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- (I bet people will do so, anyway and keep mailing me "hey,
- I draw to the screen but don't see the changes"...)
- - Another nice trick is to use drawing routines to draw
- something at area 2 on both display pages 0 & 1: as AniVGA
- doesn't care for this area, it will stay there. Later on,
- when you want to get rid of the changes again, you set
- UpdateOuterArea:=2 and the next call of Animate() will wipe
- out area 2 with the contents of the original background image
- again
-
- See also : SetAnimateWindow, Animate
-
-
- VIRTUAL COORDINATES - information
- ─────────────────────────────────
-
- See : coordinates
-
-
- WinClip, WinXMIN, WinXMAX, WinYMIN, WinYMAX - information
- ─────────────────────────────────────────────────────────
-
- Normally, the screen area (0,0)..(XMAX,YMAX) is identical to your animation
- window (WinXMIN,WinYMIN)..(WinXMAX,WinYMAX), so clipping is unnecessary.
- However, if you used SetAnimateWindow to define an animation window smaller
- than your screen, (WinXMIN,WinYMIN)..(WinXMAX,WinYMAX) hold the boundaries
- of this window.
- This implies some special requirements: if you have a line, which lies
- partially _outside_ the animation window, but still on the screen, should
- this part be visible or not? Since there are good reasons for either case,
- you decide how AniVGA shall treat this case: if you set WinClip:=TRUE, all
- lines will be clipped to the animation window. WinClip:=FALSE (the default
- value) prevents clipping so that you may draw to the outer area, too.
-
- Note (!) : - Only WinClip should be changed directly, all others are read-
- only and shouldn't be changed other than by SetAnimateWindow!
-
- See also : SetAnimateWindow
-
-
- WriteBackgroundPage - procedure
- ───────────────────────────────
-
- Function : Saves the background image to disk
-
- Declaration: PROCEDURE WriteBackgroundPage(name:STRING); FAR;
-
- Description: This is merely a shortcut of the WritePage()-procedure (see
- there), i.e. WritePage(name; BACKGNDPAGE) would do an equivalent
- job.
-
- Note : Possible ERROR-values returned are Err_FileIO
-
- See also : WritePage
-
-
- WritePage - procedure
- ─────────────────────
-
- Function : Saves a graphic page to disk
-
- Declaration: PROCEDURE WritePage(name:STRING; pa:WORD); FAR;
-
- Description: To save an image of one of the drawing pages (0 or 1), the
- backgroundpage BACKGNDPAGE (=2) or SCROLLPAGE (=3), specify the
- approriate page number in "pa" and a valid MSDOS-path/name where
- to store the data in "name".
-
- Note : - Make sure that your disk has enough space to hold the data: one
- page is stored as 64003 bytes!
- - You can't use this procedure for saving the background page
- "pa"=SCROLLPAGE in background mode SCROLLING!
- - Possible ERROR-values returned are: Err_InvalidPageNumber and
- Err_FileIO
-
- See also : WriteBackgroundPage, LoadPage
-
-
- XMAX - constant
- ───────────────
-
- Function : Specifies the maximal absolute x-coordinate
-
- Declaration: CONST XMAX=319
-
- Description: XMAX is the biggest _absolute_ coordinate in the x-direction
- which can be used: all x-coordinates must lie in the range
- 0..XMAX.
-
- Note : Probably, you will never use this constant at all, because nearly
- everything in AniVGA's user interface works with _virtual_ coor-
- dinates, but who can tell...
-
- See also : YMAX, coordinates
-
-
- XTiles - variable
- ─────────────────
-
- Function : Holds the width of the scrollable background image in tiles
-
- Declaration: VAR XTiles:INTEGER;
-
- Description: When using background mode SCROLLING, you have to specify the
- size of your scrolling background area (with the
- SetBackgroundScrollRange()-procedure). AniVGA adjusts these
- values slightly and computes the size of the resulting background
- image in tiles.
- The width of this area (in tiles) is then stored in XTiles.
-
- Note : Don't change this variable directly!
-
- See also : YTiles, Background, SetBackgroundScrollRange
-
-
- YMAX - constant
- ───────────────
-
- Function : Specifies the maximal absolute y-coordinate
-
- Declaration: CONST YMAX=199
-
- Description: YMAX is the biggest _absolute_ y-coordinate which may be used,
- that is, every y-coordinate must lie in the range 0..YMAX.
-
- Note : Probably, you will never use this constant at all, because nearly
- everything in AniVGA's user interface works with _virtual_ coor-
- dinates, but who can tell...
-
- See also : XMAX, coordinates
-
-
- YTiles - variable
- ─────────────────
-
- Function : Holds the height of the scrollable background image in tiles
-
- Declaration: VAR YTiles:INTEGER;
-
- Description: When using background mode SCROLLING, you have to specify the
- size of your scrolling background area (with the
- SetBackgroundScrollRange()-procedure). AniVGA adjusts these
- values slightly and computes the size of the resulting background
- image in tiles.
- The height of this area (in tiles) is then stored in YTiles.
-
- Note : Don't change this variable directly!
-
- See also : XTiles, Background, SetBackgroundScrollRange
-